Ok, Now I've got a Parser that create an 'AST' (see code below) from
valid BF code.
Any suggestions on how return the positions of invalid chars.
My thought is to encode a rule, which matches anything that isn't not
a CMD / While Loop. ( How to encode a not?)
[code]
using Nemerle.Collections;
using Nemerle.Peg;
using Nemerle.Text;
using Nemerle.Utility;
using Nemerle;
using System;
using System.Collections.Generic;
using SCG = System.Collections.Generic;
using Nemerle.Peg.AstUtils;
namespace BF
{
variant bfc
{ | Add { pos: int }
| Sub { pos: int }
| Dec { pos: int }
| Inc { pos: int }
| C_in { pos: int }
| Cout { pos: int }
| W_beg { pos: int }
| W_end { pos: int }
| While { begin: W_beg;
end: W_end;
expr: List[bfc];
}
}
[PegGrammar(Options = EmitDebugSources, cmds,
grammar
{newLine = "\n"
/ "\r\n"
/ "\r"
/ "\u2028" /* line separator */
/ "\u2029"; /* paragraph separator */
cmd_cmd : bfc = '+'/'-'/'<'/'>'/'?'/'.';
begin_while : bfc = '[';
end_while : bfc = ']';
while_loop : bfc = begin_while cmds* end_while;
cmds : List[bfc] =(while_loop / cmd_cmd)+ newLine? ;
})]
class Parser
{
cmd_cmd(t:NToken):bfc
{ match (this._parsingSource.OriginalText[t.StartPos])
{ | '+' => bfc.Add(t.StartPos);
| '-' => bfc.Sub(t.StartPos);
| '>' => bfc.Inc(t.StartPos);
| '<' => bfc.Dec(t.StartPos);
| '?' => bfc.C_in(t.StartPos);
| '.' => bfc.Cout(t.StartPos);
| _ => throw InvalidOperationException()
}
}
begin_while (t:NToken):bfc { bfc.W_beg(t.StartPos) }
end_while (t:NToken):bfc { bfc.W_end(t.StartPos) }
cmds (cs:List[bfc], n : NToken) : List[bfc] { cs}
while_loop (p0:bfc ,p1 :List[List[bfc]], p2 : bfc) : bfc.While
{ bfc.While(p0:>bfc.W_beg,p2:>bfc.W_end, p1[0] ) }
}
}
[/code]