mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
* tests/local.at (AT_FOR_EACH_SKEL): New. Use where appropriate. * data/skeletons/lalr1.d: Reject -d. * tests/input.at, tests/scanner.at: Also check D.
335 lines
7.5 KiB
Plaintext
335 lines
7.5 KiB
Plaintext
# Interface with the scanner. -*- Autotest -*-
|
|
|
|
# Copyright (C) 2019-2021 Free Software Foundation, Inc.
|
|
|
|
# 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 <https://www.gnu.org/licenses/>.
|
|
|
|
AT_BANNER([[Interface with the scanner.]])
|
|
|
|
|
|
# -------------- #
|
|
# AT_RAW_YYLEX. #
|
|
# -------------- #
|
|
|
|
m4_pushdef([AT_RAW_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
|
|
|
|
m4_define([AT_RAW_YYLEX(c)],
|
|
[#include <stdlib.h> /* abort */
|
|
AT_YYLEX_PROTOTYPE[
|
|
{
|
|
static const char* input = "0-(1+2)*3/9";
|
|
int c = *input++;
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
]AT_VAL[.val = c - '0';
|
|
return NUM;
|
|
case '+': return PLUS;
|
|
case '-': return MINUS;
|
|
case '*': return STAR;
|
|
case '/': return SLASH;
|
|
case '(': return LPAR;
|
|
case ')': return RPAR;
|
|
case 0: return 0;
|
|
}
|
|
abort ();
|
|
}
|
|
]])
|
|
|
|
m4_define([AT_RAW_YYLEX(c++)],
|
|
[#include <stdlib.h> /* abort */
|
|
AT_YYLEX_PROTOTYPE[
|
|
{
|
|
static const char* input = "0-(1+2)*3/9";
|
|
int c = *input++;
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':]AT_TOKEN_CTOR_IF([[
|
|
return yy::parser::make_NUM (c - '0');]], [[
|
|
]AT_VAL[.val = c - '0';
|
|
return yy::parser::token::NUM;]])[
|
|
case '+': return yy::parser::]AT_TOKEN_CTOR_IF([make_PLUS ()], [token::PLUS])[;
|
|
case '-': return yy::parser::]AT_TOKEN_CTOR_IF([make_MINUS ()], [token::MINUS])[;
|
|
case '*': return yy::parser::]AT_TOKEN_CTOR_IF([make_STAR ()], [token::STAR])[;
|
|
case '/': return yy::parser::]AT_TOKEN_CTOR_IF([make_SLASH ()], [token::SLASH])[;
|
|
case '(': return yy::parser::]AT_TOKEN_CTOR_IF([make_LPAR ()], [token::LPAR])[;
|
|
case ')': return yy::parser::]AT_TOKEN_CTOR_IF([make_RPAR ()], [token::RPAR])[;
|
|
case 0: return yy::parser::]AT_TOKEN_CTOR_IF([make_END ()], [token::END])[;
|
|
}
|
|
abort ();
|
|
}
|
|
]])
|
|
|
|
m4_define([AT_RAW_YYLEX(d)],
|
|
[[import std.range.primitives;
|
|
import std.stdio;
|
|
|
|
auto yyLexer(R)(R range)
|
|
if (isInputRange!R && is (ElementType!R : dchar))
|
|
{
|
|
return new YYLexer!R(range);
|
|
}
|
|
|
|
auto yyLexer ()
|
|
{
|
|
return yyLexer("0-(1+2)*3/9");
|
|
}
|
|
|
|
class YYLexer(R) : Lexer
|
|
if (isInputRange!R && is (ElementType!R : dchar))
|
|
{
|
|
R input;
|
|
|
|
this(R r) { input = r; }
|
|
|
|
]AT_YYERROR_DEFINE[
|
|
|
|
Symbol yylex ()
|
|
{
|
|
import std.uni : isNumber;
|
|
// Handle EOF.
|
|
if (input.empty)
|
|
return Symbol(TokenKind.END);
|
|
|
|
auto c = input.front;
|
|
input.popFront;
|
|
|
|
// Numbers.
|
|
switch (c)
|
|
{
|
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
return Symbol(TokenKind.NUM, c - '0');
|
|
case '+': return Symbol(TokenKind.PLUS);
|
|
case '-': return Symbol(TokenKind.MINUS);
|
|
case '*': return Symbol(TokenKind.STAR);
|
|
case '/': return Symbol(TokenKind.SLASH);
|
|
case '(': return Symbol(TokenKind.LPAR);
|
|
case ')': return Symbol(TokenKind.RPAR);
|
|
default: assert(0);
|
|
}
|
|
}
|
|
}
|
|
]])
|
|
|
|
m4_pushdef([AT_MAIN_DEFINE(d)],
|
|
[[int main ()
|
|
{
|
|
auto l = yyLexer ();
|
|
auto p = new YYParser (l);
|
|
return !p.parse ();
|
|
}]])
|
|
|
|
|
|
m4_pushdef([AT_MAIN_DEFINE(java)],
|
|
[[class input
|
|
{
|
|
public static void main (String[] args) throws IOException
|
|
{]AT_LEXPARAM_IF([[
|
|
]AT_PARSER_CLASS[ p = new ]AT_PARSER_CLASS[ (System.in);]], [[
|
|
]AT_API_prefix[Lexer l = new ]AT_API_prefix[Lexer (System.in);
|
|
]AT_PARSER_CLASS[ p = new ]AT_PARSER_CLASS[ (l);]])AT_DEBUG_IF([[
|
|
//p.setDebugLevel (1);]])[
|
|
boolean success = p.parse ();
|
|
if (!success)
|
|
System.exit (1);
|
|
}
|
|
}]])
|
|
|
|
m4_define([AT_RAW_YYLEX(java)],
|
|
[[class CalcLexer implements Calc.Lexer {
|
|
|
|
StreamTokenizer st;
|
|
|
|
public CalcLexer(InputStream is) {
|
|
st = new StreamTokenizer(new StringReader("0-(1+2)*3/9"));
|
|
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 EOF;
|
|
case StreamTokenizer.TT_EOL:
|
|
return (int) '\n';
|
|
case StreamTokenizer.TT_WORD:
|
|
yylval = Integer.parseInt(st.sval);
|
|
return NUM;
|
|
case '+':
|
|
return PLUS;
|
|
case '-':
|
|
return MINUS;
|
|
case '*':
|
|
return STAR;
|
|
case '/':
|
|
return SLASH;
|
|
case '(':
|
|
return LPAR;
|
|
case ')':
|
|
return RPAR;
|
|
default:
|
|
throw new AssertionError("invalid character: " + ttype);
|
|
}
|
|
}
|
|
}
|
|
]])
|
|
|
|
|
|
## ------------------- ##
|
|
## Raw token numbers. ##
|
|
## ------------------- ##
|
|
|
|
m4_pushdef([AT_TEST],
|
|
[
|
|
AT_SETUP([Token numbers: $1])
|
|
|
|
AT_BISON_OPTION_PUSHDEFS([%debug ]m4_bmatch([$1], [java], [[%define api.prefix {Calc} %define api.parser.class {Calc}]])[ $1])
|
|
AT_DATA_GRAMMAR([[input.y]],
|
|
[[$1
|
|
%debug
|
|
]AT_LANG_MATCH([[c\|c++]], [[
|
|
%code
|
|
{
|
|
#include <stdio.h>
|
|
]AT_YYERROR_DECLARE[
|
|
]AT_YYLEX_DECLARE[
|
|
}]],
|
|
[java], [[
|
|
%define api.prefix {Calc}
|
|
%define api.parser.class {Calc}
|
|
%code imports {
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.StringReader;
|
|
import java.io.Reader;
|
|
import java.io.StreamTokenizer;
|
|
}
|
|
]])[
|
|
|
|
]AT_LANG_MATCH([c\|c++\|d],
|
|
[AT_VARIANT_IF([[
|
|
%token <int> NUM "number"
|
|
%nterm <int> exp
|
|
]], [[
|
|
%union {
|
|
int val;
|
|
}
|
|
%token <val> NUM "number"
|
|
%nterm <val> exp
|
|
]])],
|
|
[java],
|
|
[[%token <Integer> NUM "number"
|
|
%type <Integer> exp
|
|
]])[
|
|
|
|
%token
|
|
PLUS "+"
|
|
MINUS "-"
|
|
STAR "*"
|
|
SLASH "/"
|
|
LPAR "("
|
|
RPAR ")"
|
|
END 0
|
|
|
|
%left "+" "-"
|
|
%left "*" "/"
|
|
|
|
%%
|
|
|
|
input
|
|
: exp { ]AT_JAVA_IF([[System.out.println ($][1)]], [[printf ("%d\n", $][1)]])[; }
|
|
;
|
|
|
|
exp
|
|
: exp "+" exp { $][$][ = $][1 + $][3; }
|
|
| exp "-" exp { $][$][ = $][1 - $][3; }
|
|
| exp "*" exp { $][$][ = $][1 * $][3; }
|
|
| exp "/" exp { $][$][ = $][1 / $][3; }
|
|
| "(" exp ")" { $][$][ = $][2; }
|
|
| "number" { $][$][ = $][1; }
|
|
;
|
|
|
|
%%
|
|
]AT_LANG_MATCH([c\|c++\|d],
|
|
[AT_YYERROR_DEFINE])[
|
|
]AT_RAW_YYLEX[
|
|
]AT_MAIN_DEFINE[
|
|
]])
|
|
|
|
AT_FULL_COMPILE([input])
|
|
|
|
# When api.token.raw, the yytranslate table should not be included.
|
|
#
|
|
# yacc.c, glr.c and glr.cc use 'yytranslate' (and YYTRANSLATE).
|
|
# lalr1.cc uses 'translate_table' (and yytranslate_).
|
|
# lalr1.d uses 'byte[] translate_table =' (and yytranslate_).
|
|
# lalr1.java uses 'byte[] translate_table_ =' (and yytranslate_).
|
|
AT_CHECK([[$EGREP -c 'yytranslate\[\]|translate_table\[\]|translate_table =|translate_table_ =' input.]AT_LANG_EXT],
|
|
[ignore],
|
|
[AT_D_IF([AT_TOKEN_RAW_IF([0], [0])],
|
|
[AT_TOKEN_RAW_IF([0], [1])])[
|
|
]])
|
|
|
|
|
|
AT_PARSER_CHECK([input], 0,
|
|
[[-1
|
|
]])
|
|
|
|
AT_BISON_OPTION_POPDEFS
|
|
AT_CLEANUP
|
|
])
|
|
|
|
AT_FOR_EACH_SKEL(
|
|
[AT_TEST([%skeleton "]b4_skel["])
|
|
AT_TEST([%skeleton "]b4_skel[" %define api.token.raw])])
|
|
|
|
AT_TEST([%skeleton "lalr1.cc" %define api.token.raw %define api.value.type variant %define api.token.constructor])])
|
|
|
|
m4_popdef([AT_MAIN_DEFINE(java)])
|
|
m4_popdef([AT_MAIN_DEFINE(d)])
|
|
m4_popdef([AT_TEST])
|