Update URLs to prefer https: to http:
[bison.git] / examples / java / calc / Calc.y
blob53b01b801d36990501fda46cb3a7cfaaa935c367
1 /* Parser and scanner for calc in Java. -*- Java -*-
3 Copyright (C) 2018-2021 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>. */
20 %language "Java"
22 %define api.parser.class {Calc}
23 %define api.parser.public
24 %define api.push-pull push
26 %define parse.error custom
27 %define parse.trace
29 %locations
31 %code imports {
32 import java.io.BufferedReader;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.io.Reader;
37 import java.io.StreamTokenizer;
38 import java.nio.CharBuffer;
41 %code {
42 public static void main(String[] args) throws IOException {
43 CalcLexer scanner = new CalcLexer(System.in);
44 Calc parser = new Calc(scanner);
45 for (String arg : args)
46 if (arg.equals("-p"))
47 parser.setDebugLevel(1);
48 int status;
49 do {
50 int token = scanner.getToken();
51 Object lval = scanner.getValue();
52 Calc.Location yyloc = scanner.getLocation();
53 status = parser.push_parse(token, lval, yyloc);
54 } while (status == Calc.YYPUSH_MORE);
55 if (status != Calc.YYACCEPT)
56 System.exit(1);
59 static String i18n(String s) {
60 return s;
64 /* Bison Declarations */
65 %token
66 BANG "!"
67 PLUS "+"
68 MINUS "-"
69 STAR "*"
70 SLASH "/"
71 CARET "^"
72 LPAREN "("
73 RPAREN ")"
74 EQUAL "="
75 EOL _("end of line")
76 <Integer>
77 NUM _("number")
78 %type <Integer> exp
80 %nonassoc "=" /* comparison */
81 %left "-" "+"
82 %left "*" "/"
83 %precedence NEG /* negation--unary minus */
84 %right "^" /* exponentiation */
86 /* Grammar follows */
88 input:
89 line
90 | input line
93 line:
94 EOL
95 | exp EOL { System.out.println($exp); }
96 | error EOL
99 exp:
100 NUM { $$ = $1; }
101 | exp "=" exp
103 if ($1.intValue() != $3.intValue())
104 yyerror(@$, "calc: error: " + $1 + " != " + $3);
106 | exp "+" exp { $$ = $1 + $3; }
107 | exp "-" exp { $$ = $1 - $3; }
108 | exp "*" exp { $$ = $1 * $3; }
109 | exp "/" exp { $$ = $1 / $3; }
110 | "-" exp %prec NEG { $$ = -$2; }
111 | exp "^" exp { $$ = (int) Math.pow($1, $3); }
112 | "(" exp ")" { $$ = $2; }
113 | "(" error ")" { $$ = 1111; }
114 | "!" { $$ = 0; return YYERROR; }
115 | "-" error { $$ = 0; return YYERROR; }
119 class CalcLexer implements Calc.Lexer {
121 StreamTokenizer st;
122 PositionReader reader;
124 public CalcLexer(InputStream is) {
125 reader = new PositionReader(new InputStreamReader(is));
126 st = new StreamTokenizer(reader);
127 st.resetSyntax();
128 st.eolIsSignificant(true);
129 st.wordChars('0', '9');
132 Position start = new Position(1, 0);
133 Position end = new Position(1, 0);
136 * The location of the last token read.
137 * Implemented with getStartPos and getEndPos in pull parsers.
139 public Calc.Location getLocation() {
140 return new Calc.Location(new Position(start), new Position(end));
144 * Build and emit a syntax error message.
146 public void reportSyntaxError(Calc.Context ctx) {
147 System.err.print(ctx.getLocation() + ": syntax error");
149 final int TOKENMAX = 10;
150 Calc.SymbolKind[] arg = new Calc.SymbolKind[TOKENMAX];
151 int n = ctx.getExpectedTokens(arg, TOKENMAX);
152 for (int i = 0; i < n; ++i)
153 System.err.print((i == 0 ? ": expected " : " or ")
154 + arg[i].getName());
157 Calc.SymbolKind lookahead = ctx.getToken();
158 if (lookahead != null)
159 System.err.print(" before " + lookahead.getName());
161 System.err.println("");
165 * Emit an error referring to the given location in a user-defined way.
167 * @@param loc The location of the element to which the
168 * error message is related.
169 * @@param msg The string for the error message.
171 public void yyerror(Calc.Location loc, String msg) {
172 if (loc == null)
173 System.err.println(msg);
174 else
175 System.err.println(loc + ": " + msg);
178 Integer yylval;
181 * The value of the last token read. Called getLVal in pull parsers.
183 public Object getValue() {
184 return yylval;
188 * Fetch the next token. Called yylex in pull parsers.
190 public int getToken() throws IOException {
191 start.set(reader.getPosition());
192 int ttype = st.nextToken();
193 end.set(reader.getPosition());
194 switch (ttype) {
195 case StreamTokenizer.TT_EOF:
196 return YYEOF;
197 case StreamTokenizer.TT_EOL:
198 end.line += 1;
199 end.column = 0;
200 return EOL;
201 case StreamTokenizer.TT_WORD:
202 yylval = new Integer(st.sval);
203 end.set(reader.getPreviousPosition());
204 return NUM;
205 case ' ': case '\t':
206 return getToken();
207 case '!':
208 return BANG;
209 case '+':
210 return PLUS;
211 case '-':
212 return MINUS;
213 case '*':
214 return STAR;
215 case '/':
216 return SLASH;
217 case '^':
218 return CARET;
219 case '(':
220 return LPAREN;
221 case ')':
222 return RPAREN;
223 case '=':
224 return EQUAL;
225 default:
226 throw new AssertionError("invalid character: " + ttype);
232 * A class defining a point in the input.
234 class Position {
235 public int line = 1;
236 public int column = 1;
238 public Position() {
239 line = 1;
240 column = 1;
243 public Position(int l, int t) {
244 line = l;
245 column = t;
248 public Position(Position p) {
249 line = p.line;
250 column = p.column;
253 public void set(Position p) {
254 line = p.line;
255 column = p.column;
258 public boolean equals(Position l) {
259 return l.line == line && l.column == column;
262 public String toString() {
263 return Integer.toString(line) + "." + Integer.toString(column);
266 public int line() {
267 return line;
270 public int column() {
271 return column;
276 * A Stream reader that keeps track of the current Position.
278 class PositionReader extends BufferedReader {
280 private Position position = new Position();
281 // Position before the latest call to "read", i.e. position
282 // of the last character of the current token.
283 private Position previousPosition = new Position();
285 public PositionReader(Reader reader) {
286 super(reader);
289 public int read() throws IOException {
290 previousPosition.set(position);
291 int res = super.read();
292 if (res > -1) {
293 char c = (char) res;
294 if (c == '\r' || c == '\n') {
295 position.line += 1;
296 position.column = 1;
297 } else {
298 position.column += 1;
301 return res;
304 public Position getPosition() {
305 return position;
308 public Position getPreviousPosition() {
309 return previousPosition;