Parse EBNF: Difference between revisions

Added Algol 68
m (syntax highlighting fixup automation)
(Added Algol 68)
 
(3 intermediate revisions by 2 users not shown)
Line 11:
See [[Parse EBNF/Tests|the tests]].
<br><br>
 
=={{header|ALGOL 68}}==
 
The source of the Algol 68 sample is somewhat largish, so is on a separate page on Rosetta Code here: [[Parse EBNF/ALGOL 68]].
{{out}}
<pre>
Valid EBNF: a/z: 'a' { a = 'a1' ( 'a2' | 'a3' ) { 'a4' } [ 'a5' ] 'a6' ; } 'z'
a: seq
literal "a1"
oneof
seq
literal "a2"
seq
literal "a3"
list
literal "a4"
opt
literal "a5"
literal "a6"
 
 
"a1a3a4a4a5a6" is valid according to a
 
"a1 a2a6" is valid according to a
 
"a1 a3 a4 a6" is valid according to a
 
**** Syntax error near "a1 a4 a5 a6"
"a1 a4 a5 a6" is not valid according to a
 
**** Syntax error near "a5 a5 a6"
"a1 a2 a4 a5 a5 a6" is not valid according to a
 
**** Unexpected text: "a7" at the end of source
"a1 a2 a4 a5 a6 a7" is not valid according to a
 
**** Syntax error near "your ad here"
"your ad here" is not valid according to a
 
 
Valid EBNF: Arithmetic expressions:
'Arithmetic expressions'
{
expr = term { plus term } .
term = factor { times factor } .
factor = number | '(' expr ')' .
plus = '+' | '-' .
times = '*' | '/' .
number = digit { digit } .
digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
}
expr: seq
rule term
list
rule plus
rule term
term: seq
rule factor
list
rule times
rule factor
factor: oneof
seq
rule number
seq
literal "("
rule expr
literal ")"
plus: oneof
seq
literal "+"
seq
literal "-"
times: oneof
seq
literal "*"
seq
literal "/"
number: seq
rule digit
list
rule digit
digit: oneof
seq
literal "0"
seq
literal "1"
seq
literal "2"
seq
literal "3"
seq
literal "4"
seq
literal "5"
seq
literal "6"
seq
literal "7"
seq
literal "8"
seq
literal "9"
 
 
"2" is valid according to Arithmetic expressions
 
"2*3 + 4/23 - 7" is valid according to Arithmetic expressions
 
"(3 + 4) * 6-2+(4*(4))" is valid according to Arithmetic expressions
 
**** Syntax error near "-2"
"-2" is not valid according to Arithmetic expressions
 
**** Unexpected text: "+" at the end of source
"3 +" is not valid according to Arithmetic expressions
 
**** Syntax error near " 3"
"(4 + 3" is not valid according to Arithmetic expressions
 
 
**** Expected "{", not "a"
Invalid EBNF: a = '1';
 
**** Expected "}", not "(eof)"
Invalid EBNF: { a = '1' ;
 
**** Expected "=", not "world"
Invalid EBNF: { hello world = '1'; }
 
**** Rule "bar" not defined
Invalid EBNF: { foo = bar . }
</pre>
 
=={{header|Go}}==
Line 1,835 ⟶ 1,968:
It is implemented and exercised using the flavor of EBNF and test cases specified on the [[Parse EBNF/Tests|test page]].
 
<syntaxhighlight lang="raku" line># A Raku grammar to parse EBNF
# A Raku grammar toEBNF parse EBNF{
rule TOP { ^ <title>? '{' [ <production> ]+ '}' <comment>? $ }
grammar EBNF {
rule rule TOPproduction { ^ <titlename>? '{=' [ <productionexpression> <[.;]+ '}' <comment>? $ }
rule productionexpression { <nameterm> '='+% <expression> <[.;]>"|" }
rule expression term { <termfactor> +% "|" }
rule factor { <group> | <repeat> | <optional> | <identifier> | <literal> }
rule term { <factor>+ }
rule factor { <group> |{ <repeat> |'(' <optionalexpression> | <identifier> | <literal>')' }
rule rule group repeat { '({' <expression> ')}' }
rule rule repeatoptional { '{[' <expression> '}]' }
token identifier { <-[\|\(\)\{\}\[\]\.\;\"\'\s]>+ } #"
rule optional { '[' <expression> ']' }
token identifier literal { ["'" <-[\|\(\)\{\}\[\']\.\;\>+ "\'\s" | '"' <-["]>+ '"'] } #"
token token literal { ["'" <-[']>+ "'"title | '"'{ <-["]literal>+ '"'] } #"
token token titlecomment { <literal> }
token comment name { <literalidentifier> <?before \h* '='> }
}
token name { <identifier> <?before \h* '='> }
 
}
class EBNF::Actions {
class EBNF::Actions {
method TOP($/) {
say "Syntax Tree:\n", $/; # Dump the syntax tree to STDOUT
Line 1,861 ⟶ 1,993:
">]+\$\}\n " ~ $<production>>>.ast ~ "\}"
}
method production($/) {
make 'token ' ~ $<name> ~ ' {' ~
$<expression>.ast ~ "}\n"
}
method expression($/) { make join '|', $<term>>>.ast }
method term($/) { make join '\h*', $<factor>>>.ast }
method factor($/) {
make $<literal> ?? $<literal> !!
$<group> ?? '[' ~ $<group>.ast ~ ']' !!
Line 1,874 ⟶ 2,006:
'<' ~ $<identifier> ~ '>'
}
method repeat($/) { make $<expression>.ast }
method optional($/) { make $<expression>.ast }
method group($/) { make $<expression>.ast }
}
 
# An array of test cases
my @tests = (
{
ebnf =>
Line 1,937 ⟶ 2,069:
teststrings => ['foobar']
}
);
 
# Test the parser.
my $i = 1;
for @tests -> $test {
unless EBNF.parse($test<ebnf>) {
say "Parsing EBNF grammar:\n";
Line 1,972 ⟶ 2,104:
say '*' x 79, "\n";
unlink $fn;
}</syntaxhighlight>
}
</syntaxhighlight>
 
Output:
Line 2,536 ⟶ 2,667:
{{trans|Phix}}
{{libheader|Wren-fmt}}
{{libheader|Wren-traititerate}}
{{libheader|Wren-str}}
{{libheader|Wren-seq}}
Translated via the Go entry.
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Conv, Fmt
import "./traititerate" for Stepped
import "./str" for Char
import "./seq" for Lst
 
var src = ""
3,044

edits