Parse EBNF: Difference between revisions

45,141 bytes added ,  2 years ago
m
→‎{{header|Phix}}: syntax coloured
m (added whitespace and hightlighting.)
m (→‎{{header|Phix}}: syntax coloured)
Line 1,226:
 
=={{header|Phix}}==
<!--<lang Phix>string src(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer ch, sdx
<span style="color: #004080;">string</span> <span style="color: #000000;">src</span>
object token
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sdx</span>
 
<span style="color: #004080;">object</span> <span style="color: #000000;">token</span>
bool error = false
function invalid(string msg)
<span style="color: #004080;">bool</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
error = true
<span style="color: #008080;">function</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
?msg
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
sdx = length(src)+1 -- (set to eof)
<span style="color: #0000FF;">?</span><span style="color: #000000;">msg</span>
return -1
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- (set to eof)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure skip_spaces()
while 1 do
<span style="color: #008080;">procedure</span> <span style="color: #000000;">skip_spaces</span><span style="color: #0000FF;">()</span>
if sdx>length(src) then exit end if
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
ch = src[sdx]
<span style="color: #008080;">if</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if not find(ch," \t\r\n") then exit end if
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]</span>
sdx += 1
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\t'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\r'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
procedure get_token()
-- yeilds a single character token, one of {}()[]|=.;
<span style="color: #008080;">procedure</span> <span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
-- or {"terminal",string} or {"ident", string} or -1.
<span style="color: #000080;font-style:italic;">-- yeilds a single character token, one of {}()[]|=.;
skip_spaces()
-- or {"terminal",string} or {"ident", string} or -1.</span>
if sdx>length(src) then
<span style="color: #000000;">skip_spaces</span><span style="color: #0000FF;">()</span>
token = -1
<span style="color: #008080;">if</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
return
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
end if
<span style="color: #008080;">return</span>
integer tokstart = sdx
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if find(ch,"{}()[]|=.;") then
<span style="color: #004080;">integer</span> <span style="color: #000000;">tokstart</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sdx</span>
sdx += 1
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"{}()[]|=.;"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
token = ch
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
elsif ch='\"'
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
or ch='\'' then
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\"'</span>
integer closech = ch
<span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;"><nowiki>'\''</nowiki></span> <span style="color: #008080;">then</span>
for tokend=sdx+1 to length(src) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">closech</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
if src[tokend] = closech then
<span style="color: #008080;">for</span> <span style="color: #000000;">tokend</span><span style="color: #0000FF;">=</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
sdx = tokend+1
<span style="color: #008080;">if</span> <span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tokend</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">closech</span> <span style="color: #008080;">then</span>
token = {"terminal",src[tokstart+1..tokend-1]}
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tokend</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
return
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"terminal"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tokstart</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">tokend</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]}</span>
end if
<span style="color: #008080;">return</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
token = invalid("no closing quote")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
elsif ch>='a' and ch<='z' then
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"no closing quote"</span><span style="color: #0000FF;">)</span>
-- to simplify things for the purposes of this task,
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'a'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'z'</span> <span style="color: #008080;">then</span>
-- identifiers are strictly a-z only, not A-Z or 1-9
<span style="color: #000080;font-style:italic;">-- to simplify things for the purposes of this task,
while 1 do
-- identifiers are sdxstrictly +=a-z only, not A-Z or 1-9</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
if sdx>length(src) then exit end if
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
ch = src[sdx]
<span style="color: #008080;">if</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if ch<'a' or ch>'z' then exit end if
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]</span>
end while
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #008000;">'a'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'z'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
token = {"ident",src[tokstart..sdx-1]}
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
else
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"ident"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tokstart</span><span style="color: #0000FF;">..</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]}</span>
token = invalid("invalid ebnf")
<span style="color: #008080;">else</span>
end if
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf"</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
procedure match_token(integer ch)
if token!=ch then
<span style="color: #008080;">procedure</span> <span style="color: #000000;">match_token</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
token = invalid(sprintf("invalid ebnf (%c expected)",ch))
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf (%c expected)"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">))</span>
get_token()
<span style="color: #008080;">else</span>
end if
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
sequence idents = {},
ididx = {}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">idents</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
 
<span style="color: #000000;">ididx</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
function add_ident(string ident)
integer k = find(ident,idents)
<span style="color: #008080;">function</span> <span style="color: #000000;">add_ident</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ident</span><span style="color: #0000FF;">)</span>
if k=0 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ident</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idents</span><span style="color: #0000FF;">)</span>
idents = append(idents,ident)
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
k = length(idents)
<span style="color: #000000;">idents</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idents</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ident</span><span style="color: #0000FF;">)</span>
ididx = append(ididx,0)
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idents</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">ididx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ididx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
return k
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">k</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
forward function expression()
 
<span style="color: #008080;">forward</span> <span style="color: #008080;">function</span> <span style="color: #000000;">expression</span><span style="color: #0000FF;">()</span>
function factor()
object res
<span style="color: #008080;">function</span> <span style="color: #000000;">factor</span><span style="color: #0000FF;">()</span>
if sequence(token) then
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span>
if token[1]="ident" then
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
token &= add_ident(token[2])
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"ident"</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">token</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">add_ident</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
res = token
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
get_token()
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">token</span>
elsif token='[' then
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'['</span> <span style="color: #008080;">then</span>
res = {"optional",expression()}
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
match_token(']')
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"optional"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expression</span><span style="color: #0000FF;">()}</span>
elsif token='(' then
<span style="color: #000000;">match_token</span><span style="color: #0000FF;">(</span><span style="color: #008000;">']'</span><span style="color: #0000FF;">)</span>
get_token()
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'('</span> <span style="color: #008080;">then</span>
res = expression()
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
match_token(')')
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">expression</span><span style="color: #0000FF;">()</span>
elsif token='{' then
<span style="color: #000000;">match_token</span><span style="color: #0000FF;">(</span><span style="color: #008000;">')'</span><span style="color: #0000FF;">)</span>
get_token()
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'{'</span> <span style="color: #008080;">then</span>
res = {"repeat",expression()}
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
match_token('}')
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"repeat"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expression</span><span style="color: #0000FF;">()}</span>
else
<span style="color: #000000;">match_token</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'}'</span><span style="color: #0000FF;">)</span>
?9/0 -- erm??
<span style="color: #008080;">else</span>
-- res = -1 -- ""
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- erm??
end if
-- res = -1 -- ""</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function term()
-- sequence res = {"factors",factor()} -- (opted against this)
<span style="color: #008080;">function</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">()</span>
sequence res = {factor()}
<span style="color: #000080;font-style:italic;">-- sequence res = {"factors",factor()} -- (opted against this)</span>
while not find(token,{-1,'|','.',';',')',']','}'}) do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">factor</span><span style="color: #0000FF;">()}</span>
res = append(res,factor())
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">,{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'|'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">';'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">')'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">']'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'}'</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">factor</span><span style="color: #0000FF;">())</span>
if length(res)=1 then res = res[1] end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return res
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function expression()
object res = term()
<span style="color: #008080;">function</span> <span style="color: #000000;">expression</span><span style="color: #0000FF;">()</span>
if token='|' then
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">()</span>
res = {"or",res}
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'|'</span> <span style="color: #008080;">then</span>
while token='|' do
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"or"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span>
get_token()
<span style="color: #008080;">while</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'|'</span> <span style="color: #008080;">do</span>
res = append(res,term())
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
end while
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">term</span><span style="color: #0000FF;">())</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence productions = {}
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">productions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
function production()
-- returns a token or -1; the real result is left in productions[] etc.
<span style="color: #008080;">function</span> <span style="color: #000000;">production</span><span style="color: #0000FF;">()</span>
get_token()
<span style="color: #000080;font-style:italic;">-- returns a token or -1; the real result is left in productions[] etc.</span>
if token!='}' then
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
if token=-1 then
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'}'</span> <span style="color: #008080;">then</span>
return invalid("invalid ebnf (missing closing })")
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf (missing closing })"</span><span style="color: #0000FF;">)</span>
if not sequence(token)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
or token[1]!="ident" then
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
return -1
<span style="color: #008080;">or</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"ident"</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
string ident = token[2]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer idx = add_ident(ident)
<span style="color: #004080;">string</span> <span style="color: #000000;">ident</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
get_token()
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">add_ident</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ident</span><span style="color: #0000FF;">)</span>
match_token('=')
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
if token=-1 then
<span style="color: #000000;">match_token</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'='</span><span style="color: #0000FF;">)</span>
return -1
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
sequence res = expression()
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
productions = append(productions,{ident,idx,res})
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">expression</span><span style="color: #0000FF;">()</span>
ididx[idx] = length(productions)
<span style="color: #000000;">productions</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">productions</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ident</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
end if
<span style="color: #000000;">ididx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">productions</span><span style="color: #0000FF;">)</span>
return token
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">token</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence extras = {}
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">extras</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
function parse(string ebnf)
-- returns: +1 if ok, -1 if bad
<span style="color: #008080;">function</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ebnf</span><span style="color: #0000FF;">)</span>
puts(1,"parse: "&ebnf&" ===>\n")
<span style="color: #000080;font-style:italic;">-- returns: +1 if ok, -1 if bad</span>
error = false
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"parse: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">ebnf</span><span style="color: #0000FF;">&</span><span style="color: #008000;">" ===&gt;\n"</span><span style="color: #0000FF;">)</span>
src = ebnf
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
sdx = 1
<span style="color: #000000;">src</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ebnf</span>
idents = {}
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
ididx = {}
<span style="color: #000000;">idents</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
productions = {}
<span style="color: #000000;">ididx</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
extras = {}
<span style="color: #000000;">productions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
get_token()
<span style="color: #000000;">extras</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
if sequence(token) then
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
token[1] = "title"
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
extras = append(extras,token)
<span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"title"</span>
get_token()
<span style="color: #000000;">extras</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">extras</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
if token!='{' then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return invalid("invalid ebnf (missing opening {)")
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'{'</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf (missing opening {)"</span><span style="color: #0000FF;">)</span>
while 1 do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
token = production()
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
if token='}' or token=-1 then exit end if
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">production</span><span style="color: #0000FF;">()</span>
end while
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'}'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
get_token()
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if sequence(token) then
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
token[1] = "comment"
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
extras = append(extras,token)
<span style="color: #000000;">token</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"comment"</span>
get_token()
<span style="color: #000000;">extras</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">extras</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
if token!=-1 then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return invalid("invalid ebnf (missing eof?)")
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf (missing eof?)"</span><span style="color: #0000FF;">)</span>
if error then return -1 end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer k = find(0,ididx)
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if k!=0 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ididx</span><span style="color: #0000FF;">)</span>
return invalid("invalid ebnf (undefined:"&idents[k]&")")
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">invalid</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid ebnf (undefined:"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">idents</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]&</span><span style="color: #008000;">")"</span><span style="color: #0000FF;">)</span>
ppOpt({pp_Pause,0})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
pp(productions)
<span style="color: #7060A8;">ppOpt</span><span style="color: #0000FF;">({</span><span style="color: #004600;">pp_Pause</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span>
-- pp(idents)
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">productions</span><span style="color: #0000FF;">)</span>
-- pp(ididx)
<span style="color: #000080;font-style:italic;">-- pp(idents)
-- pp(extras)
-- pp(ididx)
return 1
-- pp(extras)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- The rules that applies() has to deal with are:
-- {factors} - if rule[1] is not string, just apply one after the other,
<span style="color: #000080;font-style:italic;">-- The rules that applies() has to deal with are:
-- recursively. As per term() above, originally had "factors",
-- {factors} - if rule[1] is not string, just apply one after the other,
-- but getting rid of it made the syntax tree much clearer)
-- recursively. As per term() above, originally had "factors",
-- {"terminal", "a1"} -- literal constants
-- but getting rid of it made the syntax tree much clearer)
-- {"or", <e1>, <e2>, ...} -- (any) one of n
-- {"repeatterminal", <e1>"a1"} -- as per "{}" inliteral ebnfconstants
-- {"optionalor", <&lt;e1>} &gt;, &lt;e2&gt;, ...} -- as(any) per "[]"one inof ebnfn
-- {"identrepeat", <name>, idx&lt;e1&gt;} -- applyas theper sub-rule"{}" in ebnf
-- {"optional", &lt;e1&gt;} -- as per "[]" in ebnf
 
-- {"ident", &lt;name&gt;, idx} -- apply the sub-rule</span>
function applies(sequence rule)
integer was_sdx = sdx -- in case of failure
<span style="color: #008080;">function</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">rule</span><span style="color: #0000FF;">)</span>
object r1 = rule[1]
<span style="color: #004080;">integer</span> <span style="color: #000000;">was_sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sdx</span> <span style="color: #000080;font-style:italic;">-- in case of failure</span>
if not string(r1) then
<span style="color: #004080;">object</span> <span style="color: #000000;">r1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for i=1 to length(rule) do
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
if not applies(rule[i]) then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
sdx = was_sdx
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
return false
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">was_sdx</span>
end if
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
elsif r1="terminal" then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
skip_spaces()
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"terminal"</span> <span style="color: #008080;">then</span>
for i=1 to length(rule[2]) do
<span style="color: #000000;">skip_spaces</span><span style="color: #0000FF;">()</span>
if sdx>length(src)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
or src[sdx]!=rule[2][i] then
<span style="color: #008080;">if</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span>
sdx = was_sdx
<span style="color: #008080;">or</span> <span style="color: #000000;">src</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
return false
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">was_sdx</span>
end if
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
sdx += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
elsif r1="or" then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=2 to length(rule) do
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"or"</span> <span style="color: #008080;">then</span>
if applies(rule[i]) then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
return true
<span style="color: #008080;">if</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sdx = was_sdx
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return false
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">was_sdx</span>
elsif r1="repeat" then
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
while applies(rule[2]) do
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"repeat"</span> <span style="color: #008080;">then</span>
end while
<span style="color: #008080;">while</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
elsif r1="optional" then
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if applies(rule[2]) then
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"optional"</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
elsif r1="ident" then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer i = rule[3],
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"ident"</span> <span style="color: #008080;">then</span>
ii = ididx[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rule</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span>
if not applies(productions[ii][3]) then
<span style="color: #000000;">ii</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ididx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
sdx = was_sdx
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">productions</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ii</span><span style="color: #0000FF;">][</span><span style="color: #000000;">3</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
return false
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">was_sdx</span>
end if
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
?9/0
<span style="color: #008080;">else</span>
end if
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span>
return true
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure check_valid(string test)
src = test
<span style="color: #008080;">procedure</span> <span style="color: #000000;">check_valid</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
sdx = 1
<span style="color: #000000;">src</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test</span>
bool res = applies(productions[1][3])
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
skip_spaces()
<span style="color: #004080;">bool</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">applies</span><span style="color: #0000FF;">(</span><span style="color: #000000;">productions</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">3</span><span style="color: #0000FF;">])</span>
if sdx<=length(src) then res = false end if
<span style="color: #000000;">skip_spaces</span><span style="color: #0000FF;">()</span>
?{test,{"pass","fail"}[2-res]}
<span style="color: #008080;">if</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<span style="color: #0000FF;">?{</span><span style="color: #000000;">test</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"pass"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"fail"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">res</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
constant ebnf = {"""
"a" {
<span style="color: #008080;">constant</span> <span style="color: #000000;">ebnf</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"""
a = "a1" ( "a2" | "a3" ) { "a4" } [ "a5" ] "a6" ;
} "za" """,{
a = "a1" ( "a2" | "a3" ) { "a4" } [ "a5" ] "a6" ;
"""
} "z" """</span><span style="color: #0000FF;">,</span>
{
<span style="color: #008000;">"""
expr = term { plus term } .
{
term = factor { times factor } .
factor expr = numberterm |{ '('plus exprterm ')'} .
term = factor { times factor } .
plus factor = "+"number | "-"'(' expr ')' .
times = "*" | "/" .
plus = "+" | "-" .
number =times digit= {"*" digit| }"/" .
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
number = digit { digit } .
}""",
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
`a = "1"`,
}"""</span><span style="color: #0000FF;">,</span>
`{ a = "1" ;`,
<span style="color: #008000;">`a = "1"`</span><span style="color: #0000FF;">,</span>
`{ hello world = "1"; }`,
<span style="color: #008000;">`{ a = "1" ;`</span><span style="color: #0000FF;">,</span>
`{ foo = bar . }`
<span style="color: #008000;">`{ hello world = "1"; }`</span><span style="color: #0000FF;">,</span>
}
<span style="color: #008000;">`{ foo = bar . }`</span>
 
<span style="color: #0000FF;">}</span>
constant tests = { {"a1a3a4a4a5a6",
"a1 a2a6",
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"a1a3a4a4a5a6"</span><span style="color: #0000FF;">,</span>
"a1 a3 a4 a6",
<span style="color: #008000;">"a1 a4a2a6"</span><span a5style="color: a6#0000FF;">,</span>
<span style="color: #008000;">"a1 a2a3 a4 a5a6"</span><span a5style="color: a6#0000FF;">,</span>
<span style="color: #008000;">"a1 a2 a4 a5 a6"</span><span style="color: a7#0000FF;">,</span>
<span style="yourcolor: ad#008000;">"a1 a2 a4 a5 a5 a6"</span><span style="color: here#0000FF;"}>,</span>
<span style="color: #008000;">"a1 a2 a4 a5 a6 a7"</span><span style="color: #0000FF;">,</span>
{"2",
<span style="2*3color: +#008000;">"your 4ad here"</23span><span -style="color: 7#0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"2"</span><span style="color: #0000FF;">,</span>
"(3 + 4) * 6-2+(4*(4))",
<span style="color: #008000;">"-2*3 + 4/23 - 7"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"(3 + 4) * 6-2+(4*(4))"</span><span style="color: #0000FF;">,</span>
<span style="(4color: +#008000;">"-2"</span><span style="color: 3#0000FF;"}}>,</span>
<span style="color: #008000;">"3 +"</span><span style="color: #0000FF;">,</span>
 
<span style="color: #008000;">"(4 + 3"</span><span style="color: #0000FF;">}}</span>
for i=1 to length(ebnf) do
if parse(ebnf[i])=+1 then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ebnf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
?"tests:"
<span style="color: #008080;">if</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ebnf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])=+</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
for j=1 to length(tests[i]) do
<span style="color: #0000FF;">?</span><span style="color: #008000;">"tests:"</span>
check_valid(tests[i][j])
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">check_valid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</lang>-->
In real use, I would be tempted to use numeric literals rather than string tags in such structures, but the latter certainly make things ten times easier to debug, plus I got an instantly legible syntax tree dump (the bit just after "===>" below) practically for free.
{{out}}
7,803

edits