This page presents a program to check parenthesis validity
in a c, cpp, perl etc...
It is implemented as part of a c++ (cpp)
series of exercises
, that I did.
-
As an exercise to study and practice c++, I decided to
write a program, which checks the validity of parenthesis,
curly braces etc. The rule says, that each open parenthesis
must have a close one ((->).{->}).
-
The file gets a configuration file as the first
argument. This is shown in the following, triple single parenthesis, example:
(;)
{;}
[;]
-
The program builds a data base of parenthesis lookup. It
uses a class as a basic data base item:
- class c_block_member {
- public:
- c_block_member(string st_file_input, string::size_type pos);
- string st_b_start;
- string st_b_end;
- };
- c_block_member::c_block_member(string st_file_input, string::size_type pos) {
- //(;)
- st_b_start=st_file_input.substr(0, pos++);
- st_b_end =st_file_input.substr(pos, st_file_input.size());
- }//c_block_member::c_block_member
Each time a line is read from the configuration file, it
is checked, parenthesis are extracted and stored in a list of
c_block_member classes.
- infile.open (argv[1], ios::in);
- if(infile.is_open()) {
- c_block_i=0;
- while(getline(infile,st)) {
- pos = st.find(';');
- if(pos == string::npos) {
- cout << "bad input " << st << endl;
- return(0);
- } else {
- p = new c_block_member(st, pos);
- l_block.push_back(*p);
- c_block_i++;
- }
- if(c_block_i >= MAX_BLOCKS) {
- cout << "too many block descriptors " << endl;
- break;
- }
- delete p;
- }//while
- } else {
- cout << "can not open " << argv[1] << " for reading parentheses data" << endl;
- }
-
To check the validity of the file another list of classes
is used. It has a start and stop class members and some debug
info (like line number and line content). I use two
functions to add an element and its debug info, when an
open parentheses is encountered. Once an end one
is matched, it must be the one which closes the last
element in the list.
- if(s_start.compare(l_c_parentheses.back().st_p_start) == 0) {//equal
- l_c_parentheses.pop_back();
- } else {
- cout << "error for parentheses " << st << endl;
The file is read line by line. Each line is processed
character by character using string iterator:
- while(getline(infile,st)) {
- for(s_it = st.begin(); s_it != st.end(); ++s_it) {//extract one char from line
- for(it=l_block.begin(); it != l_block.end(); it++) {
- sc=*s_it;
- if(sc.compare(it->st_b_end) == 0) check_p_end(sc);
-
The code uses assert statement to stop on error. For
instance an end parentheses must have a start one:
- //Get the start parentheses
- string s_start;
- for(b_it=l_block.begin(); b_it != l_block.end(); b_it++) {
- if(b_it->st_b_end == st) {
- s_start = b_it->st_b_start;
- break;
- }
- }
- assert(s_start.size() != 0);
Some tips for debugging the program using gdb:
b parentheses.cpp:104
r parentheses.txt parentheses.cpp
printf "%s", st._M_dataplus._M_p
It is also useful to create a gdb file with common
used commands. In this simple case, run is always used with
c and c++ parentheses file input. A break point plus print
commands to be exectuted on break are also added.
define r1
run parentheses.txt $arg0
end
b parentheses.cpp:151
b parentheses.cpp:158
command 1
p p
end
#can be replaced by
define d1
display p
end
#gdb --command=parentheses_gdb.txt a.out
Now you only need to type the cpp input file:
r1 program.cpp
The code of the
c++
parentheses.cpp is available on this site.
|