/* Simple parser and scanner in Java. -*- Java -*- Copyright (C) 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ %language "Java" %define api.parser.class {Calc} %define api.parser.public %define parse.error verbose %code imports { import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StreamTokenizer; } %code { public static void main(String[] args) throws IOException { CalcLexer l = new CalcLexer(System.in); Calc p = new Calc(l); if (!p.parse()) System.exit(1); } } /* Bison Declarations */ %token NUM "number" %type exp %nonassoc '=' /* comparison */ %left '-' '+' %left '*' '/' %precedence NEG /* negation--unary minus */ %right '^' /* exponentiation */ /* Grammar follows */ %% input: line | input line ; line: '\n' | exp '\n' { System.out.println($exp); } | error '\n' ; exp: NUM { $$ = $1; } | exp '=' exp { if ($1.intValue() != $3.intValue()) yyerror("calc: error: " + $1 + " != " + $3); } | exp '+' exp { $$ = $1 + $3; } | exp '-' exp { $$ = $1 - $3; } | exp '*' exp { $$ = $1 * $3; } | exp '/' exp { $$ = $1 / $3; } | '-' exp %prec NEG { $$ = -$2; } | exp '^' exp { $$ = (int) Math.pow($1, $3); } | '(' exp ')' { $$ = $2; } | '(' error ')' { $$ = 1111; } | '!' { $$ = 0; return YYERROR; } | '-' error { $$ = 0; return YYERROR; } ; %% class CalcLexer implements Calc.Lexer { StreamTokenizer st; public CalcLexer(InputStream is) { st = new StreamTokenizer(new InputStreamReader(is)); st.resetSyntax(); st.eolIsSignificant(true); st.whitespaceChars('\t', '\t'); st.whitespaceChars(' ', ' '); st.wordChars('0', '9'); } public void yyerror(String s) { System.err.println(s); } Integer yylval; public Object getLVal() { return yylval; } public int yylex() throws IOException { int ttype = st.nextToken(); switch (ttype) { case StreamTokenizer.TT_EOF: return YYEOF; case StreamTokenizer.TT_EOL: return (int) '\n'; case StreamTokenizer.TT_WORD: yylval = Integer.parseInt(st.sval); return NUM; default: return ttype; } } }