Mercurial > jwe > qt-gui-with-push-parser
annotate parser.yy @ 12:894be158b32d
define parser as a class and eliminate some global variables
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 23 May 2019 17:57:20 -0400 |
parents | b652a5528fb1 |
children | d179b0bb85e4 |
rev | line source |
---|---|
0 | 1 // Infix notation calculator. |
2 | |
3 %{ | |
4 | |
5 #define YYSTYPE double | |
6 | |
7 #include <iostream> | |
4
0e154787183d
new interpreter and qt_interpreter objects
John W. Eaton <jwe@octave.org>
parents:
1
diff
changeset
|
8 #include <string> |
0 | 9 |
10 #include <cctype> | |
11 #include <cmath> | |
12 #include <cstdio> | |
13 | |
4
0e154787183d
new interpreter and qt_interpreter objects
John W. Eaton <jwe@octave.org>
parents:
1
diff
changeset
|
14 #include "interpreter.h" |
0e154787183d
new interpreter and qt_interpreter objects
John W. Eaton <jwe@octave.org>
parents:
1
diff
changeset
|
15 #include "parser.h" |
0 | 16 |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
17 namespace calc |
0 | 18 { |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
19 static void *create_parser_state (void); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
20 static void delete_parser_state (void *); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
21 |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
22 parser::parser (interpreter& interp) |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
23 : m_interpreter (interp), |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
24 m_parser_state (create_parser_state ()), |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
25 m_beg_of_stmt (true) |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
26 { } |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
27 |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
28 parser::~parser (void) |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
29 { |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
30 delete_parser_state (m_parser_state); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
31 } |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
32 |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
33 void parser::emit_error (const char *msg) const |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
34 { |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
35 m_interpreter.emit_error (msg); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
36 } |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
37 |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
38 void parser::emit_result (double value) const |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
39 { |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
40 m_interpreter.emit_result (value); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
41 } |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
42 |
11
b652a5528fb1
handle EOF on input; more misc refactoring
John W. Eaton <jwe@octave.org>
parents:
9
diff
changeset
|
43 // For communication between the lexer and parser. |
0 | 44 size_t bufptr = 0; |
45 size_t chunk_size = 0; | |
11
b652a5528fb1
handle EOF on input; more misc refactoring
John W. Eaton <jwe@octave.org>
parents:
9
diff
changeset
|
46 const char *buf; |
0 | 47 |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
48 static int yylex (YYSTYPE& token_value); |
0 | 49 } |
50 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
51 static void yyerror (calc::parser&, char const *); |
6
1b575145197e
interpreter is now a class instead of a namespace with functions
John W. Eaton <jwe@octave.org>
parents:
4
diff
changeset
|
52 |
0 | 53 %} |
54 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
55 %define api.pure full |
0 | 56 %define api.push-pull push |
57 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
58 %parse-param {calc::parser& parser} |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
59 |
0 | 60 // Bison declarations. |
61 %token NUM | |
62 %left '-' '+' | |
63 %left '*' '/' | |
64 %left NEG // negation--unary minus | |
65 %right '^' // exponentiation | |
66 | |
67 %% | |
68 | |
69 input : // empty | |
70 { } | |
71 | input line | |
1
08df60a01bc1
debug flag, handle input with signal
John W. Eaton <jwe@octave.org>
parents:
0
diff
changeset
|
72 | error |
08df60a01bc1
debug flag, handle input with signal
John W. Eaton <jwe@octave.org>
parents:
0
diff
changeset
|
73 { |
08df60a01bc1
debug flag, handle input with signal
John W. Eaton <jwe@octave.org>
parents:
0
diff
changeset
|
74 YYABORT; |
08df60a01bc1
debug flag, handle input with signal
John W. Eaton <jwe@octave.org>
parents:
0
diff
changeset
|
75 } |
0 | 76 ; |
77 | |
78 line : ';' | |
79 { } | |
80 | exp ';' | |
81 { | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
82 parser.emit_result ($1); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
83 parser.beg_of_stmt (true); |
0 | 84 } |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
85 ; |
0 | 86 |
87 exp : NUM | |
88 { | |
89 $$ = $1; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
90 parser.beg_of_stmt (false); |
0 | 91 } |
92 | exp '+' exp | |
93 { | |
94 $$ = $1 + $3; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
95 parser.beg_of_stmt (false); |
0 | 96 } |
97 | exp '-' exp | |
98 { | |
99 $$ = $1 - $3; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
100 parser.beg_of_stmt (false); |
0 | 101 } |
102 | exp '*' exp | |
103 { | |
104 $$ = $1 * $3; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
105 parser.beg_of_stmt (false); |
0 | 106 } |
107 | exp '/' exp | |
108 { | |
109 $$ = $1 / $3; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
110 parser.beg_of_stmt (false); |
0 | 111 } |
112 | '-' exp %prec NEG | |
113 { | |
114 $$ = -$2; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
115 parser.beg_of_stmt (false); |
0 | 116 } |
117 | exp '^' exp | |
118 { | |
119 $$ = std::pow ($1, $3); | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
120 parser.beg_of_stmt (false); |
0 | 121 } |
122 | '(' exp ')' | |
123 { | |
124 $$ = $2; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
125 parser.beg_of_stmt (false); |
0 | 126 } |
127 ; | |
128 | |
129 %% | |
130 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
131 namespace calc |
0 | 132 { |
133 // The lexical analyzer returns a double floating point number on the | |
134 // stack and the token NUM, or the numeric code of the character read | |
135 // if not a number. It skips all blanks and tabs, and returns -1 for | |
136 // end-of-input. | |
137 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
138 static int yylex (YYSTYPE& token_value) |
0 | 139 { |
140 int c; | |
141 | |
142 if (bufptr >= chunk_size) | |
143 return -1; | |
144 | |
145 // Skip white space. | |
146 while ((c = buf[bufptr++]) == ' ' || c == '\t' || c == '\n') | |
147 ; | |
148 | |
149 // Process numbers. | |
150 if (c == '.' || isdigit (c)) | |
151 { | |
152 int chars_read = 0; | |
153 bufptr--; | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
154 sscanf (&buf[bufptr], "%lf%n", &token_value, &chars_read); |
0 | 155 bufptr += chars_read; |
156 return NUM; | |
157 } | |
158 | |
159 // Return a single char. | |
160 return c; | |
161 } | |
162 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
163 int parser::parse_and_execute (const std::string& line) |
0 | 164 { |
165 bufptr = 0; | |
166 chunk_size = line.length (); | |
167 buf = line.c_str (); | |
168 | |
169 int status; | |
170 | |
171 do | |
172 { | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
173 YYSTYPE token_value; |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
174 int input_char = yylex (token_value); |
0 | 175 |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
176 if (input_char < 0) |
0 | 177 return -1; |
178 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
179 status = yypush_parse (static_cast<yypstate *> (m_parser_state), |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
180 input_char, &token_value, *this); |
0 | 181 } |
182 while (status == YYPUSH_MORE); | |
183 | |
1
08df60a01bc1
debug flag, handle input with signal
John W. Eaton <jwe@octave.org>
parents:
0
diff
changeset
|
184 return -2; |
0 | 185 } |
186 | |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
187 static void *create_parser_state (void) |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
188 { |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
189 return yypstate_new (); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
190 } |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
191 |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
192 static void delete_parser_state (void *parser_state) |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
193 { |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
194 return yypstate_delete (static_cast<yypstate *> (parser_state)); |
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
195 } |
0 | 196 } |
6
1b575145197e
interpreter is now a class instead of a namespace with functions
John W. Eaton <jwe@octave.org>
parents:
4
diff
changeset
|
197 |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
198 static void yyerror (calc::parser& parser, char const *msg) |
6
1b575145197e
interpreter is now a class instead of a namespace with functions
John W. Eaton <jwe@octave.org>
parents:
4
diff
changeset
|
199 { |
12
894be158b32d
define parser as a class and eliminate some global variables
John W. Eaton <jwe@octave.org>
parents:
11
diff
changeset
|
200 parser.emit_error (msg); |
6
1b575145197e
interpreter is now a class instead of a namespace with functions
John W. Eaton <jwe@octave.org>
parents:
4
diff
changeset
|
201 } |