Recursive Decent parser

Hey guys, just wanted to see if you guys could catch what I can't... It runs fine except that when an invalid character is input the program loops instead of just seeking new input... Is there a flag I need to place and if so where?

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
#include <iostream>

using namespace std;

int gcd(int a, int b);
int max(int a);
int modular(int a, int b);
void command();
int expr();
int term();
int value();
int factor();
int number();
int digit();

int token;
int line = 0;
bool flag = false;

void error(char* message){
	flag = true;
	cout << "line " << line << ' ' << message << endl;
}

void getToken(){
	token = getchar();
	while(isspace(token) && token != '\n')
		token = getchar();
}

void match(char c, char*message){
	if(token == c )
		getToken();
	else
		error(message);
}

void command(){
	int result = expr();
	if(token == '\n' && flag == false){
		cout << "the result is: " << result << endl;
	}
	else{ 
		error("syntax error");
	}
}

int expr(){
	int result = term();
	while(token == '&'){
		getToken();
		result = gcd(result, term());
	}
	return result;
}

int term(){
	int result;
	if(token == '%'){
		getToken();
		result = max(value());
	}
	else
		result = value();
	return result;
}

int value(){
	int result = factor();
	while(token == '@'){
		getToken();
		result = modular(result,factor());
	}
	return result;
}

int factor(){
	int result; 
	if(token == '('){
		match('(', "( expeced");
		result = expr();
		match(')', ") expected");
	}
	else
		result = number();
	return result;
}

int number(){
	int result = digit();
	while(isdigit(token))
		result = 10*result + digit();
	return result;
}

int digit(){
	int result = 0;
	if(isdigit(token)){
		result = token - '0';
		match(token, "( expected");
		return result;
	}
	else{
		error("lexical error");
		return result;
	}
}

void parse(){
	line++;
	flag = false;
	getToken();
	command();
}

int main(){
	while(cin){
		parse();
	}
	return 0;
}

int gcd (int a, int b){
	a = a + 2;
	b = b + 3;
	int t;
	while (b != 0){ 
	t = b;
   	b = a % b;
    a = t;
	}
	return t;
}

int max(int a){
	int a1 = 5 * a;
	int a2 = 3 * a + 10;
	if(a1 > a2)
		return a1;
	else
		return a2;
}

int modular(int a, int b){
	int sol;
	a = a + 5;
 	sol = a % b;
	return sol;
}
Last edited on
If you are using while(cin) then why are you using getchar() instead of cin.get() ? I don't know if that has anything to do with the looping problem but it seems like apples and oranges.
Your use of match() puzzles me. There is only one place you use it where it could possibly not be a match and result in an error condition (when you check for the ending paren,) but you use it all over to check a condition you know will not result in an error condition.

When you say "the program loops instead of just seeking new input." What do you want the behavior to be? What input causes the behavior to be other than what you expect it to be?



well the use of while(cin) is to get input by line until eof, using while(getchar()) results in losing the first character of the line.
match() is used to call getToken()... which I could also call directly, thanks.

Well if you type in b it seems to run four, first reaching digit() and saying it is a "lexical error" then it seems to run again reaching command() and saying there is a "syntax error" and it does it again this time incrementing the line lumber
Following the logical structure of the program, when you enter "b\n",the first getToken() sets the token to 'b' and this is propagated through function calls down to digit() where the "lexical error" occurs, then it bubbles back up to command. Because the current token is still 'b' and not '\n' it prints out "syntax error" and returns to parse where the line number is increased, the next token is extracted (which happens to be '\n') and command is called again. Repeat the previous chain of events for '\n'.

It seems to me you need to ensure that command is consuming a full line of text up to and including the newline.

Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void command(){
	int result = expr();

	if ( token == '\n' && flag == false)
		cout << "the result is: " << result << endl ;
	else
	{
		if ( flag == false ) // no error message has been output yet
			error( "Syntax error") ;

		while ( token != '\n' )
			getToken();
	}
}
yea ok so the full line needed to be consumed otherwise it would take in every character and output a message until newline was reached. Thank You!
Topic archived. No new replies allowed.