1 # Interface with the scanner. -*- Autotest -*-
3 # Copyright (C) 2019-2021 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
18 AT_BANNER([[Interface with the scanner.]])
25 m4_pushdef([AT_RAW_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
27 m4_define([AT_RAW_YYLEX(c)],
28 [#include <stdlib.h> /* abort */
31 static const char* input = "0-(1+2)*3/9";
45 ]AT_VAL[.val = c - '0';
47 case '+': return PLUS;
48 case '-': return MINUS;
49 case '*': return STAR;
50 case '/': return SLASH;
51 case '(': return LPAR;
52 case ')': return RPAR;
59 m4_define([AT_RAW_YYLEX(c++)],
60 [#include <stdlib.h> /* abort */
63 static const char* input = "0-(1+2)*3/9";
76 case '9':]AT_TOKEN_CTOR_IF([[
77 return yy::parser::make_NUM (c - '0');]], [[
78 ]AT_VAL[.val = c - '0';
79 return yy::parser::token::NUM;]])[
80 case '+': return yy::parser::]AT_TOKEN_CTOR_IF([make_PLUS ()], [token::PLUS])[;
81 case '-': return yy::parser::]AT_TOKEN_CTOR_IF([make_MINUS ()], [token::MINUS])[;
82 case '*': return yy::parser::]AT_TOKEN_CTOR_IF([make_STAR ()], [token::STAR])[;
83 case '/': return yy::parser::]AT_TOKEN_CTOR_IF([make_SLASH ()], [token::SLASH])[;
84 case '(': return yy::parser::]AT_TOKEN_CTOR_IF([make_LPAR ()], [token::LPAR])[;
85 case ')': return yy::parser::]AT_TOKEN_CTOR_IF([make_RPAR ()], [token::RPAR])[;
86 case 0: return yy::parser::]AT_TOKEN_CTOR_IF([make_END ()], [token::END])[;
92 m4_define([AT_RAW_YYLEX(d)],
93 [[import std.range.primitives;
96 auto yyLexer(R)(R range)
97 if (isInputRange!R && is (ElementType!R : dchar))
99 return new YYLexer!R(range);
104 return yyLexer("0-(1+2)*3/9");
107 class YYLexer(R) : Lexer
108 if (isInputRange!R && is (ElementType!R : dchar))
112 this(R r) { input = r; }
118 import std.uni : isNumber;
121 return Symbol(TokenKind.END);
123 auto c = input.front;
129 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
130 return Symbol(TokenKind.NUM, c - '0');
131 case '+': return Symbol(TokenKind.PLUS);
132 case '-': return Symbol(TokenKind.MINUS);
133 case '*': return Symbol(TokenKind.STAR);
134 case '/': return Symbol(TokenKind.SLASH);
135 case '(': return Symbol(TokenKind.LPAR);
136 case ')': return Symbol(TokenKind.RPAR);
143 m4_pushdef([AT_MAIN_DEFINE(d)],
147 auto p = new YYParser (l);
152 m4_pushdef([AT_MAIN_DEFINE(java)],
155 public static void main (String[] args) throws IOException
157 ]AT_PARSER_CLASS[ p = new ]AT_PARSER_CLASS[ (System.in);]], [[
158 ]AT_API_prefix[Lexer l = new ]AT_API_prefix[Lexer (System.in);
159 ]AT_PARSER_CLASS[ p = new ]AT_PARSER_CLASS[ (l);]])AT_DEBUG_IF([[
160 //p.setDebugLevel (1);]])[
161 boolean success = p.parse ();
167 m4_define([AT_RAW_YYLEX(java)],
168 [[class CalcLexer implements Calc.Lexer {
172 public CalcLexer(InputStream is) {
173 st = new StreamTokenizer(new StringReader("0-(1+2)*3/9"));
175 st.eolIsSignificant(true);
176 st.whitespaceChars('\t', '\t');
177 st.whitespaceChars(' ', ' ');
178 st.wordChars('0', '9');
181 public void yyerror(String s) {
182 System.err.println(s);
187 public Object getLVal() {
191 public int yylex() throws IOException {
192 int ttype = st.nextToken();
195 case StreamTokenizer.TT_EOF:
197 case StreamTokenizer.TT_EOL:
199 case StreamTokenizer.TT_WORD:
200 yylval = Integer.parseInt(st.sval);
215 throw new AssertionError("invalid character: " + ttype);
222 ## ------------------- ##
223 ## Raw token numbers. ##
224 ## ------------------- ##
226 m4_pushdef([AT_TEST],
228 AT_SETUP([Token numbers: $1])
230 AT_BISON_OPTION_PUSHDEFS([%debug ]m4_bmatch([$1], [java], [[%define api.prefix {Calc} %define api.parser.class {Calc}]])[ $1])
231 AT_DATA_GRAMMAR([[input.y]],
234 ]AT_LANG_MATCH([[c\|c++]], [[
242 %define api.prefix {Calc}
243 %define api.parser.class {Calc}
245 import java.io.IOException;
246 import java.io.InputStream;
247 import java.io.StringReader;
248 import java.io.Reader;
249 import java.io.StreamTokenizer;
253 ]AT_LANG_MATCH([c\|c++\|d],
255 %token <int> NUM "number"
261 %token <val> NUM "number"
265 [[%token <Integer> NUM "number"
284 : exp { ]AT_JAVA_IF([[System.out.println ($][1)]], [[printf ("%d\n", $][1)]])[; }
288 : exp "+" exp { $][$][ = $][1 + $][3; }
289 | exp "-" exp { $][$][ = $][1 - $][3; }
290 | exp "*" exp { $][$][ = $][1 * $][3; }
291 | exp "/" exp { $][$][ = $][1 / $][3; }
292 | "(" exp ")" { $][$][ = $][2; }
293 | "number" { $][$][ = $][1; }
297 ]AT_LANG_MATCH([c\|c++\|d],
298 [AT_YYERROR_DEFINE])[
303 AT_FULL_COMPILE([input])
305 # When api.token.raw, the yytranslate table should not be included.
307 # yacc.c, glr.c and glr.cc use 'yytranslate' (and YYTRANSLATE).
308 # lalr1.cc uses 'translate_table' (and yytranslate_).
309 # lalr1.d uses 'byte[] translate_table =' (and yytranslate_).
310 # lalr1.java uses 'byte[] translate_table_ =' (and yytranslate_).
311 AT_CHECK([[$EGREP -c 'yytranslate\[\]|translate_table\[\]|translate_table =|translate_table_ =' input.]AT_LANG_EXT],
313 [AT_D_IF([AT_TOKEN_RAW_IF([0], [0])],
314 [AT_TOKEN_RAW_IF([0], [1])])[
318 AT_PARSER_CHECK([input], 0,
322 AT_BISON_OPTION_POPDEFS
327 [AT_TEST([%skeleton "]b4_skel["])
328 AT_TEST([%skeleton "]b4_skel[" %define api.token.raw])])
330 AT_TEST([%skeleton "lalr1.cc" %define api.token.raw %define api.value.type variant %define api.token.constructor])])
332 m4_popdef([AT_MAIN_DEFINE(java)])
333 m4_popdef([AT_MAIN_DEFINE(d)])