# HG changeset patch # User John W. Eaton # Date 1558648640 14400 # Node ID 894be158b32d4ba5669d11a0052b7b3fdef2221e # Parent b652a5528fb173c81b4ce2e600d4566de528872d define parser as a class and eliminate some global variables diff -r b652a5528fb1 -r 894be158b32d command-window.cpp --- a/command-window.cpp Thu May 23 13:42:57 2019 -0400 +++ b/command-window.cpp Thu May 23 17:57:20 2019 -0400 @@ -209,8 +209,11 @@ { erase_line (); + interpreter& interp = m_interpreter->get_interpreter (); + parser& parser = interp.get_parser (); + std::string line = rl_line_buffer ? rl_line_buffer : ""; - std::string prompt = (rl_prompt && parser::beg_of_stmt) ? rl_prompt : ""; + std::string prompt = (rl_prompt && parser.beg_of_stmt ()) ? rl_prompt : ""; insert_line (prompt, line); diff -r b652a5528fb1 -r 894be158b32d interpreter.cpp --- a/interpreter.cpp Thu May 23 13:42:57 2019 -0400 +++ b/interpreter.cpp Thu May 23 17:57:20 2019 -0400 @@ -14,7 +14,8 @@ interpreter *interpreter::the_interpreter = nullptr; interpreter::interpreter (void) - : m_error_handler ([] (const char *msg) + : m_parser (*this), + m_error_handler ([] (const char *msg) { std::cerr << "error: " << msg << std::endl; }), m_result_handler ([] (double value) { std::cout << "ans = " << value << std::endl; }) @@ -26,21 +27,14 @@ } the_interpreter = this; - - parser::init (); - } - - interpreter::~interpreter (void) - { - parser::fini (); } int interpreter::parse_and_execute (const std::string& line) { - return parser::parse_and_execute (line); + return m_parser.parse_and_execute (line); } - void interpreter::emit_result (double value) + void interpreter::emit_result (double value) const { // Simulate a delay in calculation. sleep (1); @@ -48,7 +42,7 @@ m_result_handler (value); } - void interpreter::emit_error (const char *msg) + void interpreter::emit_error (const char *msg) const { m_error_handler (msg); } diff -r b652a5528fb1 -r 894be158b32d interpreter.h --- a/interpreter.h Thu May 23 13:42:57 2019 -0400 +++ b/interpreter.h Thu May 23 17:57:20 2019 -0400 @@ -3,6 +3,8 @@ #include +#include "parser.h" + namespace calc { class interpreter @@ -17,7 +19,9 @@ interpreter& operator = (const interpreter&) = delete; - ~interpreter (void); + ~interpreter (void) = default; + + parser& get_parser (void) { return m_parser; } int parse_and_execute (const std::string& line); @@ -37,12 +41,14 @@ return tmp; } - void emit_error (const char *msg); + void emit_error (const char *msg) const; - void emit_result (double value); + void emit_result (double value) const; private: + parser m_parser; + std::function m_error_handler; std::function m_result_handler; }; diff -r b652a5528fb1 -r 894be158b32d make-log --- a/make-log Thu May 23 13:42:57 2019 -0400 +++ b/make-log Thu May 23 17:57:20 2019 -0400 @@ -1,14 +1,15 @@ bison -o parser.cpp parser.yy -parser.yy:1.1-3: error: syntax error, unexpected identifier - beg// Infix notation calculator. - ^~~ -parser.yy:59.1-4: error: syntax error, unexpected identifier: - line : ';' - ^~~~ -parser.yy:68.1-3: error: syntax error, unexpected identifier: - exp : NUM - ^~~ -parser.yy:118.3-202.0: error: syntax error, unexpected epilogue - %% - ^ -make: *** [Makefile:4: parser.cpp] Error 1 +g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -I. -isystem /usr/include/libdrm -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o parser.o parser.cpp +parser.yy:22:15: warning: ‘void calc::yyerror(calc::parser&, const char*)’ declared ‘static’ but never defined [-Wunused-function] + static void yyerror (calc::parser&, char const *); + ^~~~~~~ +parser.yy:22:15: warning: ‘void calc::yyerror(calc::parser&, const char*)’ used but never defined +parser.yy:195:13: warning: ‘void yyerror(calc::parser&, const char*)’ defined but not used [-Wunused-function] + static void yyerror (calc::parser& parser, char const *msg) + ^~~~~~~ +g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -I. -isystem /usr/include/libdrm -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o tty-main.o tty-main.cpp +tty-main.cpp: In function ‘int calc::tty_main(int, char**)’: +tty-main.cpp:29:61: error: cannot resolve overloaded function ‘beg_of_stmt’ based on conversion to type ‘bool’ + char *tmp = readline (parser::beg_of_stmt ? ">> " : ""); + ^~ +make: *** [calc.mk:454: tty-main.o] Error 1 diff -r b652a5528fb1 -r 894be158b32d parser.h --- a/parser.h Thu May 23 13:42:57 2019 -0400 +++ b/parser.h Thu May 23 17:57:20 2019 -0400 @@ -1,14 +1,40 @@ #if ! defined (calc_parse_h) #define calc_parse_h 1 -namespace parser +namespace calc { - extern bool beg_of_stmt; + class interpreter; + + class parser + { + public: + + parser (interpreter&); + + parser (const parser&) = delete; + + parser& operator = (const parser&) = delete; + + ~parser (void); - extern void init (void); - extern void fini (void); + bool beg_of_stmt (void) const { return m_beg_of_stmt; } + + void beg_of_stmt (bool flag) { m_beg_of_stmt = flag; } + + int parse_and_execute (const std::string& line); + + void emit_error (const char *msg) const; - extern int parse_and_execute (const std::string& line); + void emit_result (double value) const; + + private: + + interpreter& m_interpreter; + + void *m_parser_state; + + bool m_beg_of_stmt; + }; } #endif diff -r b652a5528fb1 -r 894be158b32d parser.yy --- 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 (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 (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 diff -r b652a5528fb1 -r 894be158b32d qt-interpreter.h --- a/qt-interpreter.h Thu May 23 13:42:57 2019 -0400 +++ b/qt-interpreter.h Thu May 23 17:57:20 2019 -0400 @@ -22,6 +22,8 @@ qt_interpreter& operator = (const qt_interpreter&) = delete; + interpreter& get_interpreter (void) { return m_interpreter; } + signals: void result_ready (double); diff -r b652a5528fb1 -r 894be158b32d tty-main.cpp --- a/tty-main.cpp Thu May 23 13:42:57 2019 -0400 +++ b/tty-main.cpp Thu May 23 17:57:20 2019 -0400 @@ -24,9 +24,11 @@ calc::interpreter interp; + calc::parser& parser = interp.get_parser (); + for (;;) { - char *tmp = readline (parser::beg_of_stmt ? ">> " : ""); + char *tmp = readline (parser.beg_of_stmt () ? ">> " : ""); if (! tmp) {