86 lines
1.7 KiB
Perl
86 lines
1.7 KiB
Perl
use strict;
|
|
use warnings;
|
|
|
|
use lib qw( t/lib );
|
|
|
|
use Test::More;
|
|
use ANTLR::Runtime::Test;
|
|
|
|
plan tests => 1;
|
|
|
|
# The SimpleCalc grammar from the five minutes tutorial.
|
|
g_test_output_is({ grammar => <<'GRAMMAR', test_program => <<'CODE', expected => <<'OUTPUT' });
|
|
grammar Expr;
|
|
options { language = Perl5; }
|
|
@header {}
|
|
|
|
@members {
|
|
my %memory;
|
|
}
|
|
|
|
prog: stat+ ;
|
|
|
|
stat: expr NEWLINE { print "$expr.value\n"; }
|
|
| ID '=' expr NEWLINE
|
|
{ $memory{$ID.text} = $expr.value; }
|
|
| NEWLINE
|
|
;
|
|
|
|
expr returns [value]
|
|
: e=multExpr { $value = $e.value; }
|
|
( '+' e=multExpr { $value += $e.value; }
|
|
| '-' e=multExpr { $value -= $e.value; }
|
|
)*
|
|
;
|
|
|
|
multExpr returns [value]
|
|
: e=atom { $value = $e.value; } ('*' e=atom { $value *= $e.value; })*
|
|
;
|
|
|
|
atom returns [value]
|
|
: INT { $value = $INT.text; }
|
|
| ID
|
|
{
|
|
my $v = $memory{$ID.text};
|
|
if (defined $v) {
|
|
$value = $v;
|
|
} else {
|
|
print STDERR "undefined variable $ID.text\n";
|
|
}
|
|
}
|
|
| '(' expr ')' { $value = $expr.value; }
|
|
;
|
|
|
|
ID : ('a'..'z'|'A'..'Z')+ ;
|
|
INT : '0'..'9'+ ;
|
|
NEWLINE:'\r'? '\n' ;
|
|
WS : (' '|'\t')+ { $self->skip(); } ;
|
|
GRAMMAR
|
|
use strict;
|
|
use warnings;
|
|
|
|
use ANTLR::Runtime::ANTLRStringStream;
|
|
use ANTLR::Runtime::CommonTokenStream;
|
|
use ExprLexer;
|
|
use ExprParser;
|
|
|
|
my $in = << 'EOT';
|
|
1 + 1
|
|
8 - 1
|
|
a = 10
|
|
b = 13
|
|
2 * a + b + 1
|
|
EOT
|
|
|
|
my $input = ANTLR::Runtime::ANTLRStringStream->new({ input => $in });
|
|
my $lexer = ExprLexer->new({ input => $input });
|
|
|
|
my $tokens = ANTLR::Runtime::CommonTokenStream->new({ token_source => $lexer });
|
|
my $parser = ExprParser->new({ input => $tokens });
|
|
$parser->prog();
|
|
CODE
|
|
2
|
|
7
|
|
34
|
|
OUTPUT
|