%language "Java" %define api.parser.class {Calc} %define api.parser.public %define parse.error verbose %define parse.trace %locations %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); for (String arg : args) if (arg.equals ("-p")) p.setDebugLevel (1); 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'); } Position yypos = new Position (1, 0); public Position getStartPos () { return yypos; } public Position getEndPos () { return yypos; } public void yyerror (Calc.Location l, String s) { if (l == null) System.err.println (s); else System.err.println (l + ": " + s); } Integer yylval; public Object getLVal () { return yylval; } public int yylex () throws IOException { int ttype = st.nextToken (); yypos = new Position (yypos.lineno (), yypos.token () + 1); if (ttype == st.TT_EOF) return EOF; else if (ttype == st.TT_EOL) { yypos = new Position (yypos.lineno () + 1, 0); return (int) '\n'; } else if (ttype == st.TT_WORD) { yylval = new Integer (st.sval); return NUM; } else return st.ttype; } } class Position { public int line; public int token; public Position () { line = 0; token = 0; } public Position (int l, int t) { line = l; token = t; } public boolean equals (Position l) { return l.line == line && l.token == token; } public String toString () { return Integer.toString (line) + "." + Integer.toString(token); } public int lineno () { return line; } public int token () { return token; } }