Mercurial > jwe > qt-gui-with-push-parser
view parse.yy @ 1:08df60a01bc1
debug flag, handle input with signal
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 20 May 2019 13:45:58 -0400 |
parents | dff751fb985c |
children |
line wrap: on
line source
// Infix notation calculator. %{ #define YYSTYPE double #include <iostream> #include <cctype> #include <cmath> #include <cstdio> #include <unistd.h> #include "main.h" #include "gui-main.h" #include "tty-main.h" #include "parse.h" namespace interpreter { FILE *outfile = 0; size_t bufptr = 0; size_t chunk_size = 0; const char *buf; bool beg_of_stmt = true; static int yylex (void); static void debug_trace (const char *); } static void yyerror (char const *); %} %define api.push-pull push // Bison declarations. %token NUM %left '-' '+' %left '*' '/' %left NEG // negation--unary minus %right '^' // exponentiation %% input : // empty { } | input line | error { interpreter::debug_trace ("ABORT"); YYABORT; } ; line : ';' { } | exp ';' { interpreter::emit_result ($1); interpreter::beg_of_stmt = true; } ; exp : NUM { interpreter::debug_trace ("NUM"); $$ = $1; interpreter::beg_of_stmt = false; } | exp '+' exp { interpreter::debug_trace ("ADD"); $$ = $1 + $3; interpreter::beg_of_stmt = false; } | exp '-' exp { interpreter::debug_trace ("SUB"); $$ = $1 - $3; interpreter::beg_of_stmt = false; } | exp '*' exp { interpreter::debug_trace ("MUL"); $$ = $1 * $3; interpreter::beg_of_stmt = false; } | exp '/' exp { interpreter::debug_trace ("DIV"); $$ = $1 / $3; interpreter::beg_of_stmt = false; } | '-' exp %prec NEG { interpreter::debug_trace ("NEG"); $$ = -$2; interpreter::beg_of_stmt = false; } | exp '^' exp { interpreter::debug_trace ("EXP"); $$ = std::pow ($1, $3); interpreter::beg_of_stmt = false; } | '(' exp ')' { interpreter::debug_trace ("PAREN"); $$ = $2; interpreter::beg_of_stmt = false; } ; %% namespace interpreter { // 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) { int c; if (bufptr >= chunk_size) return -1; // Skip white space. while ((c = buf[bufptr++]) == ' ' || c == '\t' || c == '\n') ; // Process numbers. if (c == '.' || isdigit (c)) { int chars_read = 0; bufptr--; sscanf (&buf[bufptr], "%lf%n", &yylval, &chars_read); bufptr += chars_read; return NUM; } // Return a single char. return c; } static yypstate *ps = 0; void parser_fini (void) { if (ps) yypstate_delete (ps); ps = 0; } void parser_init (void) { parser_fini (); ps = yypstate_new (); } int parse_and_execute (const std::string& line) { bufptr = 0; chunk_size = line.length (); buf = line.c_str (); int status; do { ::yychar = yylex (); if (::yychar < 0) return -1; status = yypush_parse (ps); } while (status == YYPUSH_MORE); return -2; } void emit_result (double value) { // Simulate a delay in calculation. sleep (1); if (calc::tty_mode) tty::emit_result (value); else gui::emit_result (value); } void emit_error (const char *msg) { if (calc::tty_mode) tty::emit_error (msg); else gui::emit_error (msg); } void debug_trace (const char *msg) { if (calc::debug_mode) std::cerr << msg << std::endl; } } static void yyerror (char const *msg) { interpreter::emit_error (msg); }