news: update
[bison.git] / tests / scanner.at
blob44bae6e826b9f820507e92c7e2cf5956cdaf0271
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.]])
21 # -------------- #
22 # AT_RAW_YYLEX.  #
23 # -------------- #
25 m4_pushdef([AT_RAW_YYLEX],   [AT_LANG_DISPATCH([$0], $@)])
27 m4_define([AT_RAW_YYLEX(c)],
28 [#include <stdlib.h> /* abort */
29 AT_YYLEX_PROTOTYPE[
31   static const char* input = "0-(1+2)*3/9";
32   int c = *input++;
33   switch (c)
34     {
35     case '0':
36     case '1':
37     case '2':
38     case '3':
39     case '4':
40     case '5':
41     case '6':
42     case '7':
43     case '8':
44     case '9':
45       ]AT_VAL[.val = c - '0';
46       return NUM;
47     case '+': return PLUS;
48     case '-': return MINUS;
49     case '*': return STAR;
50     case '/': return SLASH;
51     case '(': return LPAR;
52     case ')': return RPAR;
53     case 0:   return 0;
54     }
55   abort ();
57 ]])
59 m4_define([AT_RAW_YYLEX(c++)],
60 [#include <stdlib.h> /* abort */
61 AT_YYLEX_PROTOTYPE[
63   static const char* input = "0-(1+2)*3/9";
64   int c = *input++;
65   switch (c)
66     {
67     case '0':
68     case '1':
69     case '2':
70     case '3':
71     case '4':
72     case '5':
73     case '6':
74     case '7':
75     case '8':
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])[;
87     }
88   abort ();
90 ]])
92 m4_define([AT_RAW_YYLEX(d)],
93 [[import std.range.primitives;
94 import std.stdio;
96 auto yyLexer(R)(R range)
97 if (isInputRange!R && is (ElementType!R : dchar))
99   return new YYLexer!R(range);
102 auto yyLexer ()
104   return yyLexer("0-(1+2)*3/9");
107 class YYLexer(R) : Lexer
108 if (isInputRange!R && is (ElementType!R : dchar))
110   R input;
112   this(R r) { input = r; }
114   ]AT_YYERROR_DEFINE[
116   Symbol yylex ()
117   {
118     import std.uni : isNumber;
119     // Handle EOF.
120     if (input.empty)
121       return Symbol(TokenKind.END);
123     auto c = input.front;
124     input.popFront;
126     // Numbers.
127     switch (c)
128     {
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);
137     default: assert(0);
138     }
139   }
143 m4_pushdef([AT_MAIN_DEFINE(d)],
144 [[int main ()
146   auto l = yyLexer ();
147   auto p = new YYParser (l);
148   return !p.parse ();
149 }]])
152 m4_pushdef([AT_MAIN_DEFINE(java)],
153 [[class input
155   public static void main (String[] args) throws IOException
156   {]AT_LEXPARAM_IF([[
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 ();
162     if (!success)
163       System.exit (1);
164   }
165 }]])
167 m4_define([AT_RAW_YYLEX(java)],
168 [[class CalcLexer implements Calc.Lexer {
170   StreamTokenizer st;
172   public CalcLexer(InputStream is) {
173     st = new StreamTokenizer(new StringReader("0-(1+2)*3/9"));
174     st.resetSyntax();
175     st.eolIsSignificant(true);
176     st.whitespaceChars('\t', '\t');
177     st.whitespaceChars(' ', ' ');
178     st.wordChars('0', '9');
179   }
181   public void yyerror(String s) {
182     System.err.println(s);
183   }
185   Integer yylval;
187   public Object getLVal() {
188     return yylval;
189   }
191   public int yylex() throws IOException {
192     int ttype = st.nextToken();
193     switch (ttype)
194       {
195       case StreamTokenizer.TT_EOF:
196         return EOF;
197       case StreamTokenizer.TT_EOL:
198         return (int) '\n';
199       case StreamTokenizer.TT_WORD:
200         yylval = Integer.parseInt(st.sval);
201         return NUM;
202       case '+':
203         return PLUS;
204       case '-':
205         return MINUS;
206       case '*':
207         return STAR;
208       case '/':
209         return SLASH;
210       case '(':
211         return LPAR;
212       case ')':
213         return RPAR;
214       default:
215         throw new AssertionError("invalid character: " + ttype);
216       }
217   }
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]],
232 [[$1
233 %debug
234 ]AT_LANG_MATCH([[c\|c++]], [[
235 %code
237 #include <stdio.h>
238 ]AT_YYERROR_DECLARE[
239 ]AT_YYLEX_DECLARE[
240 }]],
241   [java], [[
242 %define api.prefix {Calc}
243 %define api.parser.class {Calc}
244 %code imports {
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;
251 ]])[
253 ]AT_LANG_MATCH([c\|c++\|d],
254 [AT_VARIANT_IF([[
255 %token <int> NUM "number"
256 %nterm <int> exp
257 ]], [[
258 %union {
259   int val;
261 %token <val> NUM "number"
262 %nterm <val> exp
263 ]])],
264     [java],
265 [[%token <Integer> NUM "number"
266 %type  <Integer> exp
267 ]])[
269 %token
270   PLUS  "+"
271   MINUS "-"
272   STAR  "*"
273   SLASH "/"
274   LPAR  "("
275   RPAR  ")"
276   END   0
278 %left "+" "-"
279 %left "*" "/"
283 input
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])[
299 ]AT_RAW_YYLEX[
300 ]AT_MAIN_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],
312          [ignore],
313          [AT_D_IF([AT_TOKEN_RAW_IF([0], [0])],
314                   [AT_TOKEN_RAW_IF([0], [1])])[
318 AT_PARSER_CHECK([input], 0,
319 [[-1
322 AT_BISON_OPTION_POPDEFS
323 AT_CLEANUP
326 AT_FOR_EACH_SKEL(
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)])
334 m4_popdef([AT_TEST])