Create a gist now

Instantly share code, notes, and snippets.

@rns /output
Created May 8, 2015

Embed
What would you like to do?
SO q27109840 -- reject AND identifier using events
# foo.AND(5) at C:\cygwin\home\Ruslan\Marpa-R2-work\q27109840.pl line 52.
Invalid Identifier: AND at C:\cygwin\home\Ruslan\Marpa-R2-work\q27109840.pl line 73.
# foo.has(bar == 42 AND baz == 23) at C:\cygwin\home\Ruslan\Marpa-R2-work\q27109840.pl line 52.
['Expression',['Expression',['Identifier','foo']],['Identifier','has'],['Args',['ArgsList',['Expression',['Expression',['Expression',['Identifier','bar']],['Expression',['NumLiteral','42']]],['Expression',['Expression',['Identifier','baz']],['Expression',['NumLiteral','23']]]]]]]
Tool completed successfully
#!/usr/bin/perl
use 5.010;
use warnings;
use strict;
use Marpa::R2;
my $grammar = 'Marpa::R2::Scanless::G'->new(
{ bless_package => 'main',
source => \( << '__GRAMMAR__'),
:default ::= action => [ name, value]
lexeme default = action => [ name, value] latm => 1
Expression ::=
NumLiteral
| Identifier
| '(' Expression ')' assoc => group
|| Expression ('.') Identifier
|| Expression ('.') Identifier Args
| Expression ('==') Expression
|| Expression (<AND keyword>) Expression
Args ::= ('(') ArgsList (')')
ArgsList ::= Expression+ separator => [,]
Identifier ~ IdentifierHeadChar IdentifierBody
IdentifierBody ~ IdentifierBodyChar*
IdentifierHeadChar ~ [a-zA-Z_]
IdentifierBodyChar ~ [a-zA-Z0-9_]
NumLiteral ~ [0-9]+
<AND keyword> ~ 'AND'
:lexeme ~ Identifier pause => before event => 'Identifier'
:discard ~ whitespace
whitespace ~ [\s]+
__GRAMMAR__
});
use Data::Dumper;
$Data::Dumper::Indent = 0;
$Data::Dumper::Terse = 1;
$Data::Dumper::Deepcopy = 1;
TEST:
for my $input ('foo.AND(5)', 'foo.has(bar == 42 AND baz == 23)'){
warn "# $input";
my $r = Marpa::R2::Scanless::R->new( {
grammar => $grammar,
trace_terminals => 0
} );
INPUT: for(
my $pos = $r->read( \$input );
$pos < length($input);
$pos = $r->resume($pos)
) {
EVENTS: {
my ($lexeme_start, $lexeme_length) = $r->pause_span;
my $literal = $r->literal($lexeme_start, $lexeme_length);
for my $event (@{ $r->events }) {
my ($name) = @{$event};
if ($name eq 'Identifier') {
# warn "Identifier: $literal, $lexeme_start, $lexeme_length\n";
if ($literal eq 'AND'){
$r->lexeme_read('AND keyword', $lexeme_start, $lexeme_length)
// do { warn "Invalid Identifier: AND"; next TEST };
}
else{
$r->lexeme_read('Identifier', $lexeme_start, $lexeme_length);
}
$pos = $r->pos();
last EVENTS;
}
} # for my $event
}
}
say Dumper ${ $r->value };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment