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