3
\$\begingroup\$

Full code is below. Any feedback is welcomed.

I am trying to implement syntax error reporting like GCC and other interpreters/compilers. I am sure this can be improved and hence why I was pointed to this part of Stackexchange from SO.

Full program:

#include <iostream>
#include <string.h>
#include <string_view>
#include <iomanip>
#include <cstring>
#include <stack>
int main(int argc, char const *argv[])
{
 std::string code = "(* n (fac (- n 1))";
 int line = 0;
 int column = 0;
 int position = 0;
 int length = code.length();
 bool balanced;
 std::stack<char> parantheses_stack;
 for(const char c: code){
 if(c == '\n'){
 ++line;
 column = 0;
 } else {
 ++column;
 }
 if(c == ')' && parantheses_stack.empty())
 balanced = false;
 else if(c == '('){
 parantheses_stack.push(c);
 continue;
 }
 else if(!parantheses_stack.empty() && c == ')'){
 if(parantheses_stack.top() == '('){
 parantheses_stack.pop();
 }
 else if(parantheses_stack.top() != '('){
 balanced = false;
 }
 }
 }
 balanced = (!parantheses_stack.empty()) ? false : true;
 if(!balanced){
 printf("Data:\nline: %d\ncolumn: %d\nposition: %d\nlength: %d\n\n", line, column, position, length);
 printf("Syntax error:%d, %d parathesis out of balance, expected a ')'\n", line, column + 1);
 std::cout << code + "\n";
 std::cout << std::setw(column + 2) << "^\n"; 
 }
 system("pause");
 return 0;
}

Output:

enter image description here

asked Dec 28, 2023 at 17:17
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

You don't handle the case of too many closing parentheses

If there are too many closing parentheses, you set balanced = false inside the for-loop, but then continue processing characters. And the value of balanced is overwritten immediately after the end of the loop. Furthermore, you don't even have an error message for this case.

You don't need a stack

If you just want to match parentheses, and not squared/curly/angle brackets, you don't need to maintain a stack. Instead, just keep a counter for how many unmatched open brackets you have seen so far:

int balance = 0;
for (const char c: code) {
 // Count lines and columns
 if (c == '\n'){
 ++line;
 column = 0;
 continue;
 } else {
 ++column;
 }
 // Handle opening parentheses
 if (c == '(') {
 ++balance;
 continue;
 }
 // Handle closing parentheses
 if (c == ')') {
 if (--balance < 0) {
 break;
 }
 }
}

After this loop, balance should be zero. If it's negative, you know there was a closing parenthesis too many, if it's positive, there were too few.

Don't use system()

system() is a very expensive function call, since it starts a new shell process, which in turn needs to parse and handle the command "pause". Apart from being inefficient (although that doesn't matter much in this case), it is also not portable, as this will only work on Windows.

A better way is to use C++ code to wait for any character:

std::cin.get();

Although even better would be to not pause at all. If you start your program from cmd.exe, the window should not disappear. If you run it from a code editor or IDE, then check if that has an option to pause before closing the window.

Don't mix printf() and std::cout

Be consistent and use one way to print text. Since this is C++ code, stick with the C++ way to print text. If you really want to use format strings, then you'll need C++20 to get std::format(), or C++23 to get the best of both worlds with std::print(), or use the {fmt} library to get that same functionality also in older versions of C++.

Add a test suite

Make the code that checks the balance of parentheses a function that takes a string as an argument. Then you can call it multiple times. You can then make a test suite that runs it for different input strings that check different corner cases.

answered Dec 28, 2023 at 21:02
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'd suggest an even more general function which would accept opening and closing characters to check for {} or [], etc. \$\endgroup\$ Commented Dec 28, 2023 at 21:37
  • \$\begingroup\$ Hi G. Sliepen, what about error syntax reporting? I use Fmt too. \$\endgroup\$ Commented Dec 28, 2023 at 21:44

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.