check balanced parentheses

Hi! I am trying to figure out how to check if the parentheses in a file have matches. However if it is inside double quotes and // comment slash it is not counted.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

bool ArePair(char opening, char closing)
{
	if (opening == '(' && closing == ')') return true;
	else if (opening == '{' && closing == '}') return true;
	else if (opening == '[' && closing == ']') return true;
	return false;
}

void check_bracket(string line_array[], int array_size)
{
	string line;
	int index;
	char theChar;

	//go through each line
	for (index = 0; index < array_size; index++)
	{
		line = line_array[index];

		//check each char in line
		for (int i = 0; i < line.length(); i++)
		{
			if (line[i] == '/')
			{
				//go to the next line
				if (i < line.length() - 1 && line[i + 1] == '/')
				break;
			}

			//check for brackets
			//push brackets to stack
			if (line[i] == '(' || line[i] == '{' || line[i] == '[') {
				bracketStack.push(line[i]);

				//just to output stack
				while (!bracketStack.empty())
				{
					int num = 0;
					cout << ' ' << bracketStack.top();
					cout << num++;
					bracketStack.pop();
					cout << endl;
				}
			}
			else if (line[i] == ')' || line[i] == '}' || line[i] == ']')
			{
				if (bracketStack.empty() || !ArePair(bracketStack.top(), line[i]))
					cout << "Parentheses not matched" << endl;
				else
					bracketStack.pop();
			}

		}
	}


}// end check line function 
Last edited on
Just some ideas.
if it is preceded with a double quote

Shouldn't it be enclosed in quotes like "num[]" ? - in this case you can use a flag if you are in a quotation.

if (line[i] == '/') I think it would be better to check for //

1
2
3
if (line[i] == '/')
   if (i < line.length() - 1 && line[i+1] == '/')
      break;
Oh yeah when it finds the beginning quote it has to find the end quote even if it is on another line.
like this
line 1: "This is the beginning
line 2: this is the end"

that's the part I'm completely confuse because I have for loops
Are line breaks allowed in quotes?
Oh yeah you're right. but still how do I loop through the line
One idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void parse_line (const string& input, stack<char> &braces)
{
  bool in_quote = false;
  char ch = 0;

  for (size_t i = 0; i < input.size (); i++)
  {
    ch = input[i];
    switch (ch)
    {
      case '(':
      case '{':
      case '[':
        if (!in_quote)
          braces.push (ch);
        break;
      case '"':
        in_quote = !in_quote;
        break;
      case ')':
      case ']':
      case '}':
        // check if braces.count > 0 and top of stack matches the closing brace
        break;
      case '/':
        if (i < input.size () - 1 && input[i + 1] == '/')
          return; // rest of line is comment and does not concern us
        break;
    }//end of switch
  }// end of for
  if (in_quote)
  {
    // handle missing end quote
  }
}// end of  parse_line() 
I was able to handle the quotes and comments but now I'm having trouble with the missing end brackets which means there is an open bracket. How do you suggest that? and for some reason i have a sample code to check the file and its saying that the stack is not empty

this is my current code now

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void check_bracket(string line_array[], const int array_size)
{
	bool mismatch = false;
	char arrow = '^';
	int index;
	int i;
	string line;

	//read each line 
	for ( index = 0; index < array_size; index++)
	{
		line = line_array[index];
		//read each char in line
		for (i = 0; i < line.length(); i++)
		{
			if (line[i] == '/') // check if char is comment
			{
				if (i < line[i] - 1 && line[i + 1] == '/')
					break;
			}
			else if (line[i] == '"')
			{
				i++;
				while (line[i] != '"')
				{
					i++;
				}
				break;
			}
			else
			{
				switch (line[i])
				{
					//push brackets to stack
				case '(':
				case '{':
				case '[':
					bracketStack.push(line[i]);
					break;
					//check end brackets
				case ')':
				case '}':
				case ']':
					if (bracketStack.empty() || !ArePair(bracketStack.top(), line[i]))
					{
						//cout << "mismatch";
						cout << "Line " << index + 1 << ": error at column " << i + 1 << endl;
						cout << line << endl;
						cout << setw(i+1) << arrow << endl;
						mismatch = true;
					}
					else
					{
						bracketStack.pop();
					}
					break;
				default: break;
				}


			}//end else statement

		}//end for char
	}//end for line
	
	if (!bracketStack.empty())
	{
		cout << "Unmatched open paren at row " << index + 1 << " and column " << i + 1 << endl;
	}
	else if (mismatch)
	{
		cout << "MISMATCH \n\n\n\n";
	}
	else
	{
		cout << "PARENTHESES MATCH!\n\n\n";
	}
Last edited on
I would do it like that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <stdlib.h>

using namespace std;

struct Parse_error
{
  Parse_error (const int line, const int col, const string msg)
  {
    m_Line = line;
    m_Col = col;
    m_Msg = msg;
  }
  int m_Line;
  int m_Col;
  string m_Msg;
};

bool matching_braces (const char b1, const char b2)
{
  switch (b1)
  {
    case '(':
      return b2 == ')';
    case '[':
      return b2 == ']';
    case '{':
      return b2 == '}';
    default:
      return false;
  }
}

void parse_line (const string& input, stack<char> &braces)
{
  if (input.empty ())
    return;

  bool in_quote = false;
  char ch = 0;
  size_t col = 0;

  for (; col < input.size (); col++)
  {
    ch = input[col];
    switch (ch)
    {
      case '(':
      case '{':
      case '[':
        if (!in_quote)
          braces.push (ch);
        break;
      case '"':
        in_quote = !in_quote;
        break;
      case ')':
      case ']':
      case '}':
        // check if braces.count > 0 and top of stack matches the closing brace
        if (braces.empty ())
          throw Parse_error (-1, col, "Missing opening brace");
        else if (matching_braces (braces.top (), ch))
          braces.pop ();
        else
          throw Parse_error (-1, col, "Opening and closing braces don't match");
        break;
      case '/':
        if (col < input.size () - 1 && input[col + 1] == '/')
          return; // rest of line is comment and does not concern us
        break;
    } //end of switch
  } // end of for
  if (in_quote)
  {
    throw Parse_error (-1, col, "Missing closing quotation mark");
  }
}// end of  parse_line()

void parse_lines (vector<string> &lines, stack<char> &braces)
{
  for (size_t line = 0; line < lines.size (); line++)
  {
    try
    {
      parse_line (lines.at(line), braces);
    }
    catch (Parse_error& pe)
    {
      pe.m_Line = line;
      throw;
    }
  }
  if (!braces.empty ())
    throw Parse_error (-1, -1, "missing closing brace(s)");
}

void test_one ()
{
  vector<string> lines =
  {
    "void Demo();",
    "{"
    "cout << (2+3) * 5;"
    "}"
  };

  stack<char> braces;
  try
  {
    parse_lines (lines, braces);
  }
  catch (Parse_error& pe)
  {
    cerr << "** " << __FUNCTION__ << " **";
    cerr << "\nParser error:\nLine: " << pe.m_Line << "\nCol: ";
    cerr << pe.m_Col << "\nMsg: " << pe.m_Msg << "\n\n";
  }
  
}

void test_two ()
{
  vector<string> lines =
  {
    "void Demo();",
    "{"
    "cout << (2+3) * 5;"
    ""
  };

  stack<char> braces;
  try
  {
    parse_lines (lines, braces);
  }
  catch (Parse_error& pe)
  {
    cerr << "** " << __FUNCTION__ << " **";
    cerr << "\nParser error:\nLine: " << pe.m_Line << "\nCol: ";
    cerr << pe.m_Col << "\nMsg: " << pe.m_Msg << "\n\n";
  }
}

void test_three ()
{
  vector<string> lines =
  {
    "void Demo();",
    "("
    "cout << (2+3) * 5;"
    "}"
  };

  stack<char> braces;
  try
  {
    parse_lines (lines, braces);
  }
  catch (Parse_error& pe)
  {
    cerr << "** " << __FUNCTION__ << " **";
    cerr << "\nParser error:\nLine: " << pe.m_Line << "\nCol: ";
    cerr << pe.m_Col << "\nMsg: " << pe.m_Msg << "\n\n";
  }
}

int main ()
{
  test_one ();
  
  test_two ();
  
  test_three ();

  system ("pause");
  return 0;
 
}

It's not fully tested. You need to write some more tests.
Topic archived. No new replies allowed.