Parse EBNF: Difference between revisions
Content added Content deleted
m (added whitespace and hightlighting.) |
m (→{{header|Phix}}: syntax coloured) |
||
Line 1,226: | Line 1,226: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<lang Phix> |
<!--<lang Phix>(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 strictly 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 |
|||
get_token() |
<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;">" ===>\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 |
|||
-- {" |
-- {"terminal", "a1"} -- literal constants |
||
-- {" |
-- {"or", <e1>, <e2>, ...} -- (any) one of n |
||
-- {" |
-- {"repeat", <e1>} -- as per "{}" in ebnf |
||
-- {"optional", <e1>} -- as per "[]" in ebnf |
|||
-- {"ident", <name>, 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" ; |
|||
"a" { |
|||
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 } . |
|||
expr = term { plus term } . |
|||
term = factor { times factor } . |
|||
factor = number | '(' expr ')' . |
|||
times = "*" | "/" . |
|||
plus = "+" | "-" . |
|||
times = "*" | "/" . |
|||
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", |
|||
"a1 |
<span style="color: #008000;">"a1 a2a6"</span><span style="color: #0000FF;">,</span> |
||
"a1 |
<span style="color: #008000;">"a1 a3 a4 a6"</span><span style="color: #0000FF;">,</span> |
||
"a1 |
<span style="color: #008000;">"a1 a4 a5 a6"</span><span style="color: #0000FF;">,</span> |
||
" |
<span style="color: #008000;">"a1 a2 a4 a5 a5 a6"</span><span style="color: #0000FF;">,</span> |
||
<span style="color: #008000;">"a1 a2 a4 a5 a6 a7"</span><span style="color: #0000FF;">,</span> |
|||
{"2", |
|||
" |
<span style="color: #008000;">"your ad here"</span><span style="color: #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> |
||
"3 +", |
<span style="color: #008000;">"(3 + 4) * 6-2+(4*(4))"</span><span style="color: #0000FF;">,</span> |
||
" |
<span style="color: #008000;">"-2"</span><span style="color: #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. |
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}} |
{{out}} |