Created
October 1, 2014 05:20
-
-
Save rns/0371dfcffa6887f4e5a2 to your computer and use it in GitHub Desktop.
https://gist.github.com/ronsavage/a372ca2802f47808374b with series_restart()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Case: 0. In count: 1: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Output: !->! OK count: 1. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 1. In count: 2: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 2. In count: 3: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 3. In count: 4: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 4. In count: 5: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Ambiguous parse (after loop, before calling value() ). | |
Output: !->! OK count: 2. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 5. In count: 6: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 6. In count: 7: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 7. In count: 8: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse failure at (line, column) = (1, 3). | |
-------------------------------------------------- | |
Case: 8. In count: 9: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after loop, before calling value() ). | |
Output: !->! OK count: 3. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 9. In count: 10: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 4. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 10. In count: 11: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 5. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 11. In count: 12: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 6. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 12. In count: 13: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Ambiguous parse (after loop, before calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after loop, before calling value() ). | |
Output: !->! OK count: 7. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 13. In count: 14: | |
Input: !->! | |
Event Start Span Lexeme | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 8. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 14. In count: 15: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 9. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Case: 15. In count: 16: | |
Input: !->! | |
Event Start Span Lexeme | |
Parse is ambiguous: No parse (inside loop). | |
directed_edge 0 2 -> | |
edge_id: !->! | |
Parse is ambiguous: No parse (after loop, before calling value() ). | |
Output: !->! OK count: 10. | |
Ambiguous parse (after calling value() ). | |
Parse is ambiguous: Ambiguous symch at Glade=5, Symbol=<edge_statement>: | |
The ambiguity is from line 1, column 1 to line 1, column 2 | |
Text is: -> | |
There are 2 symches | |
Symch 0 is a rule: edge_statement ::= edge_name attribute_definition | |
Symch 1 is a rule: edge_statement ::= edge_name | |
(after calling value() ). | |
-------------------------------------------------- | |
Counts: in => 16. success => 10. | |
Tool completed successfully |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use 5.018; | |
use strict; | |
use utf8; | |
use warnings; | |
use warnings qw(FATAL utf8); # Fatalize encoding glitches. | |
use open qw(:std :utf8); # Undeclared streams in UTF-8. | |
use charnames qw(:full :short); # Unneeded in v5.16. | |
use Marpa::R2; | |
use Try::Tiny; | |
# -------------------------------------------------- | |
sub clean_after | |
{ | |
my($s) = @_; | |
$s =~ s/^\s+//; | |
$s =~ s/\s+$//; | |
$s =~ s/^([\"\'])(.*)\1$/$2/; # The backslashes are just for the UltraEdit syntax hiliter. | |
#$s =~ s/^\s+//; | |
#$s =~ s/\s+$//; | |
return $s; | |
} # End of clean_after. | |
# -------------------------------------------------- | |
sub clean_before | |
{ | |
my($s) = @_; | |
$s =~ s/\s*;\s*$//; | |
$s =~ s/^\s+//; | |
$s =~ s/\s+$//; | |
$s =~ s/^(<)\s+/$1/; | |
$s =~ s/\s+(>)$/$1/; | |
return $s; | |
} # End of clean_before. | |
# ------------------------------------------------ | |
sub decode_result | |
{ | |
my($result) = @_; | |
my(@worklist) = $result; | |
my($obj); | |
my($ref_type); | |
my(@stack); | |
do | |
{ | |
$obj = shift @worklist; | |
$ref_type = ref $obj; | |
if ($ref_type eq 'ARRAY') | |
{ | |
unshift @worklist, @$obj; | |
} | |
elsif ($ref_type eq 'HASH') | |
{ | |
push @stack, {%$obj}; | |
} | |
elsif ($ref_type) | |
{ | |
die "Unsupported object type $ref_type\n"; | |
} | |
else | |
{ | |
push @stack, $obj; | |
} | |
} while (@worklist); | |
return join('', @stack); | |
} # End of decode_result. | |
# -------------------------------------------------- | |
sub process | |
{ | |
my($case, $recce, $string) = @_; | |
$string = clean_before($string); | |
my($length) = length $string; | |
my($last_event) = ''; | |
my($format) = "%-20s %5s %5s %-s\n"; | |
# We use read()/lexeme_read()/resume() because we pause at each lexeme. | |
my($ambiguous_status); | |
my(@event, $event_name, $edge); | |
my(@fields); | |
my($lexeme_name, $lexeme, $literal); | |
my($span, $start); | |
print sprintf($format, 'Event', 'Start', 'Span', 'Lexeme'); | |
for | |
( | |
my $pos = $recce -> read(\$string); | |
$pos < $length; | |
$pos = $recce -> resume($pos) | |
) | |
{ | |
if ($case & 1) | |
{ | |
if ($recce -> ambiguity_metric > 1) | |
{ | |
print "Ambiguous parse (inside loop). \n"; | |
} | |
} | |
if ($case & 2) | |
{ | |
if ($ambiguous_status = $recce -> ambiguous) | |
{ | |
print "Parse is ambiguous: $ambiguous_status (inside loop). \n"; | |
} | |
} | |
@event = @{$recce -> events}; | |
#print 'Event count: ' . ($#event + 1) . ': ' . join(', ', map{${$_}[0]} @event) . ". \n"; | |
$event_name = ${$event[0]}[0]; | |
($start, $span) = $recce -> pause_span; | |
$lexeme_name = $recce -> pause_lexeme; | |
$lexeme = $recce -> literal($start, $span); | |
print sprintf($format, $lexeme_name, $start, $span, $lexeme); | |
if ($event_name eq 'attribute_name') | |
{ | |
$pos = $recce -> lexeme_read($lexeme_name); | |
$literal = substr($string, $start, $pos - $start); | |
push @fields, clean_after($literal); | |
} | |
elsif ($event_name eq 'attribute_value') | |
{ | |
$pos = $recce -> lexeme_read($lexeme_name); | |
$literal = clean_after(substr($string, $start, $pos - $start) ); | |
print "Attribute !$fields[0]! => !$fields[1]! \n"; | |
@fields = (); | |
} | |
elsif ($event_name eq 'end_attributes') | |
{ | |
$pos = $recce -> lexeme_read($lexeme_name); | |
$literal = substr($string, $start, $pos - $start); | |
} | |
elsif ($event_name eq 'start_attributes') | |
{ | |
$pos = $recce -> lexeme_read($lexeme_name); | |
$literal = substr($string, $start, $pos - $start); | |
} | |
elsif ($event_name eq 'directed_edge') | |
{ | |
$pos = $recce -> lexeme_read($lexeme_name); | |
$literal = substr($string, $start, $pos - $start); | |
print 'edge_id: !', clean_after($literal), "! \n"; | |
} | |
else | |
{ | |
die "Unexpected lexeme !$lexeme_name! with a pause. \n"; | |
} | |
$last_event = $event_name; | |
} | |
if ($case & 4) | |
{ | |
if ($recce -> ambiguity_metric > 1) | |
{ | |
print "Ambiguous parse (after loop, before calling value() ). \n"; | |
} | |
} | |
if ($case & 8) | |
{ | |
if ($ambiguous_status = $recce -> ambiguous) | |
{ | |
print "Parse is ambiguous: $ambiguous_status (after loop, before calling value() ). \n"; | |
} | |
$recce -> series_restart(); | |
} | |
# Return a defined value for success and undef for failure. | |
# The length test means we return success for empty input. | |
return $recce -> value; | |
} # End of process. | |
# ------------------------------------------------ | |
my $bnf = <<'END_OF_GRAMMAR'; | |
:default ::= action => [values] | |
lexeme default = latm => 1 # Longest Acceptable Token Match. | |
graph_grammar ::= graph_definition | |
# Graph stuff. | |
graph_definition ::= edge_statement | |
# Edge stuff | |
edge_statement ::= edge_name | |
| edge_name attribute_definition | |
edge_name ::= directed_edge | |
# Attribute stuff. | |
attribute_definition ::= attribute_statement* # The * causes the ambiguity I assume. | |
attribute_statement ::= start_attributes string_token_set end_attributes | |
string_token_set ::= string_token_pair+ | |
string_token_pair ::= attribute_name (':') attribute_value | |
# Lexemes in alphabetical order. | |
:lexeme ~ attribute_name pause => before event => attribute_name | |
attribute_name ~ string_char_set+ | |
:lexeme ~ attribute_value pause => before event => attribute_value | |
attribute_value ~ string_char_set+ | |
:lexeme ~ directed_edge pause => before event => directed_edge priority => 2 | |
directed_edge ~ '->' | |
:lexeme ~ end_attributes pause => before event => end_attributes priority => 1 | |
end_attributes ~ '}' | |
escaped_char ~ '\' [[:print:]] | |
# Use ' here just for the UltraEdit syntax hiliter. | |
:lexeme ~ start_attributes pause => before event => start_attributes | |
start_attributes ~ '{' | |
string_char_set ~ escaped_char | |
| [^;:}\]] # Neither a separator [;:] nor a terminator [}\]]. | |
# Lexemes in alphabetical order. | |
# Boilerplate. | |
:discard ~ whitespace | |
whitespace ~ [\s]+ | |
END_OF_GRAMMAR | |
my($g) = Marpa::R2::Scanless::G->new({source => \$bnf}); | |
my(%count) = (in => 0, success => 0); | |
my($ambiguous_status); | |
my($column); | |
my($input); | |
my($line); | |
my($recce); | |
my($value); | |
for my $case (0 .. 15) | |
{ | |
$count{in}++; | |
$input = '->'; | |
print "Case: $case. In count: $count{in}:\nInput: !$input! \n"; | |
$recce = Marpa::R2::Scanless::R->new | |
({ | |
grammar => $g, | |
#trace_terminals => 99, | |
}); | |
try | |
{ | |
$value = process($case, $recce, $input); | |
if (! defined $value) | |
{ | |
($line, $column) = $recce -> line_column; | |
print "Parse failure at (line, column) = ($line, $column). \n"; | |
} | |
else | |
{ | |
$count{success}++; | |
print "\tOutput: !", decode_result($$value), "! OK count: $count{success}. \n"; | |
if ($recce -> ambiguity_metric > 1) | |
{ | |
print "Ambiguous parse (after calling value() ). \n"; | |
} | |
$recce -> series_restart(); | |
if ($ambiguous_status = $recce -> ambiguous) | |
{ | |
print "Parse is ambiguous: $ambiguous_status (after calling value() ). \n"; | |
} | |
} | |
} | |
catch | |
{ | |
($line, $column) = $recce -> line_column; | |
$value = substr($input, $column - 1); | |
print "Exception: $_"; | |
print "At (line, column) = ($line, $column). Remaining text: !$value! \n"; | |
}; | |
print '-' x 50, "\n"; | |
} | |
print 'Counts: ', join('. ', map{"$_ => $count{$_}"} sort keys %count), ". \n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment