Mercurial > jwe > qt-gui-with-push-parser
diff 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 |
line wrap: on
line diff
--- a/parser.yy Thu May 23 13:42:57 2019 -0400 +++ b/parser.yy Thu May 23 17:57:20 2019 -0400 @@ -14,30 +14,49 @@ #include "interpreter.h" #include "parser.h" -namespace parser +namespace calc { + static void *create_parser_state (void); + static void delete_parser_state (void *); + + parser::parser (interpreter& interp) + : m_interpreter (interp), + m_parser_state (create_parser_state ()), + m_beg_of_stmt (true) + { } + + parser::~parser (void) + { + delete_parser_state (m_parser_state); + } + + void parser::emit_error (const char *msg) const + { + m_interpreter.emit_error (msg); + } + + void parser::emit_result (double value) const + { + m_interpreter.emit_result (value); + } + // For communication between the lexer and parser. size_t bufptr = 0; size_t chunk_size = 0; const char *buf; - // Used to tell readline whether to display the prompt indicating - // a continuation line. Is there any way we could do this job - // without a global variable? - bool beg_of_stmt = true; - - static int yylex (void); + static int yylex (YYSTYPE& token_value); } -static void yyerror (char const *); - -static void emit_error (const char *msg); -static void emit_result (double value); +static void yyerror (calc::parser&, char const *); %} +%define api.pure full %define api.push-pull push +%parse-param {calc::parser& parser} + // Bison declarations. %token NUM %left '-' '+' @@ -60,63 +79,63 @@ { } | exp ';' { - emit_result ($1); - parser::beg_of_stmt = true; + parser.emit_result ($1); + parser.beg_of_stmt (true); } -; + ; exp : NUM { $$ = $1; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | exp '+' exp { $$ = $1 + $3; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | exp '-' exp { $$ = $1 - $3; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | exp '*' exp { $$ = $1 * $3; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | exp '/' exp { $$ = $1 / $3; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | '-' exp %prec NEG { $$ = -$2; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | exp '^' exp { $$ = std::pow ($1, $3); - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } | '(' exp ')' { $$ = $2; - parser::beg_of_stmt = false; + parser.beg_of_stmt (false); } ; %% -namespace parser +namespace calc { // The lexical analyzer returns a double floating point number on the // stack and the token NUM, or the numeric code of the character read // if not a number. It skips all blanks and tabs, and returns -1 for // end-of-input. - static int yylex (void) + static int yylex (YYSTYPE& token_value) { int c; @@ -132,7 +151,7 @@ { int chars_read = 0; bufptr--; - sscanf (&buf[bufptr], "%lf%n", &yylval, &chars_read); + sscanf (&buf[bufptr], "%lf%n", &token_value, &chars_read); bufptr += chars_read; return NUM; } @@ -141,27 +160,7 @@ return c; } - // If we defined a parser object, the parser state could be a - // member variable of that object. - - static yypstate *ps = 0; - - void init (void) - { - fini (); - - ps = yypstate_new (); - } - - void fini (void) - { - if (ps) - yypstate_delete (ps); - - ps = 0; - } - - int parse_and_execute (const std::string& line) + int parser::parse_and_execute (const std::string& line) { bufptr = 0; chunk_size = line.length (); @@ -171,30 +170,32 @@ do { - ::yychar = yylex (); + YYSTYPE token_value; + int input_char = yylex (token_value); - if (::yychar < 0) + if (input_char < 0) return -1; - status = yypush_parse (ps); + status = yypush_parse (static_cast<yypstate *> (m_parser_state), + input_char, &token_value, *this); } while (status == YYPUSH_MORE); return -2; } -} -static void yyerror (char const *msg) -{ - emit_error (msg); + static void *create_parser_state (void) + { + return yypstate_new (); + } + + static void delete_parser_state (void *parser_state) + { + return yypstate_delete (static_cast<yypstate *> (parser_state)); + } } -static void emit_error (const char *msg) +static void yyerror (calc::parser& parser, char const *msg) { - calc::interpreter::the_interpreter->emit_error (msg); + parser.emit_error (msg); } - -static void emit_result (double value) -{ - calc::interpreter::the_interpreter->emit_result (value); -} \ No newline at end of file