????
Current Path : C:/opt/msys64/usr/share/doc/bison/examples/c/calc/ |
Current File : C:/opt/msys64/usr/share/doc/bison/examples/c/calc/calc.y |
%code top { #include <assert.h> #include <ctype.h> /* isdigit. */ #include <stdio.h> /* printf. */ #include <stdlib.h> /* abort. */ #include <string.h> /* strcmp. */ int yylex (void); void yyerror (char const *); } %define api.header.include {"calc.h"} /* Generate YYSTYPE from the types used in %token and %type. */ %define api.value.type union %token <double> NUM "number" %type <double> expr term fact /* Generate the parser description file (calc.output). */ %verbose /* Nice error messages with details. */ %define parse.error detailed /* Enable run-time traces (yydebug). */ %define parse.trace /* Formatting semantic values in debug traces. */ %printer { fprintf (yyo, "%g", $$); } <double>; %% /* The grammar follows. */ input: %empty | input line ; line: '\n' | expr '\n' { printf ("%.10g\n", $1); } | error '\n' { yyerrok; } ; expr: expr '+' term { $$ = $1 + $3; } | expr '-' term { $$ = $1 - $3; } | term ; term: term '*' fact { $$ = $1 * $3; } | term '/' fact { $$ = $1 / $3; } | fact ; fact: "number" | '(' expr ')' { $$ = $2; } ; %% int yylex (void) { int c; /* Ignore white space, get first nonwhite character. */ while ((c = getchar ()) == ' ' || c == '\t') continue; if (c == EOF) return 0; /* Char starts a number => parse the number. */ if (c == '.' || isdigit (c)) { ungetc (c, stdin); if (scanf ("%lf", &yylval.NUM) != 1) abort (); return NUM; } /* Any other character is a token by itself. */ return c; } /* Called by yyparse on error. */ void yyerror (char const *s) { fprintf (stderr, "%s\n", s); } int main (int argc, char const* argv[]) { /* Enable parse traces on option -p. */ for (int i = 1; i < argc; ++i) if (!strcmp (argv[i], "-p")) yydebug = 1; return yyparse (); }