Mercurial > jwe > qt-gui-with-push-parser
view parser.yy @ 4:0e154787183d
new interpreter and qt_interpreter objects
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 22 May 2019 17:30:46 -0400 |
parents | parse.yy@08df60a01bc1 |
children | 1b575145197e |
line wrap: on
line source
// Infix notation calculator. %{ #define YYSTYPE double #include <iostream> #include <string> #include <cctype> #include <cmath> #include <cstdio> #include "interpreter.h" #include "main.h" #include "gui-main.h" #include "tty-main.h" #include "parser.h" namespace parser { 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 { parser::debug_trace ("ABORT"); YYABORT; } ; line : ';' { } | exp ';' { interpreter::emit_result ($1); parser::beg_of_stmt = true; } ; exp : NUM { parser::debug_trace ("NUM"); $$ = $1; parser::beg_of_stmt = false; } | exp '+' exp { parser::debug_trace ("ADD"); $$ = $1 + $3; parser::beg_of_stmt = false; } | exp '-' exp { parser::debug_trace ("SUB"); $$ = $1 - $3; parser::beg_of_stmt = false; } | exp '*' exp { parser::debug_trace ("MUL"); $$ = $1 * $3; parser::beg_of_stmt = false; } | exp '/' exp { parser::debug_trace ("DIV"); $$ = $1 / $3; parser::beg_of_stmt = false; } | '-' exp %prec NEG { parser::debug_trace ("NEG"); $$ = -$2; parser::beg_of_stmt = false; } | exp '^' exp { parser::debug_trace ("EXP"); $$ = std::pow ($1, $3); parser::beg_of_stmt = false; } | '(' exp ')' { parser::debug_trace ("PAREN"); $$ = $2; parser::beg_of_stmt = false; } ; %% namespace parser { // 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 init (void) { fini (); ps = yypstate_new (); } void fini (void) { if (ps) yypstate_delete (ps); ps = 0; } 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 debug_trace (const char *msg) { if (calc::debug_mode) std::cerr << msg << std::endl; } } static void yyerror (char const *msg) { interpreter::emit_error (msg); }