COMPILER EBNF CHARACTERS letter = 'A'..'Z' + 'a'..'z' + '_'. digit = '0'..'9'. importantascii = ' '..'~' . noquote = importantascii - '"'. noapostrophe = importantascii - '\''. TOKENS ident = letter {letter | digit}. terminal = '"' {noquote} '"' | '\'' {noapostrophe} '\''. wrap = '\\' 'n'. IGNORE '\t' + '\r' + '\n' PRODUCTIONS EBNF = Rule {Rule}. Rule = ident (. Node n; Symbol s=Symbol.Find(t.val); //look if already known if(s==null) n=new Node(new Symbol(Node.nt,t.val)); else { if(s.typ==Node.nt) { String message="ERROR: Nonterminal symbol "+t.val+" has been defined multiple times."; EbnfForm.WriteLine(message); n=new Node(new Symbol(0,"BUG")); } else { //if only considered as terminal symbol until now s.typ=Node.nt; Symbol.terminalToNt(s.name); Symbol.terminalToNt(s.name); Node.terminalToNt(s.name); n=Node.Find(s.name); } } .) "=" Expr <out n.sym.graph> "." (. Graph.Finish(n.sym.graph); .) . Expr <out Graph g> = (. Graph g1; .) Alt <out g> (. bool first = true; .) { '|' Alt <out g1> (. if (first) { Graph.MakeFirstAlt(g); first = false; } Graph.MakeAlternative(g, g1); .) } . Alt <out Graph g> = (. Graph g1; g=new Graph(); .) {Sym <out g1> (. Graph.MakeSequence(g, g1); .) } (. if(g.l==null && g.r==null) g=new Graph(new Node(Node.eps,null)); .) . Sym <out Graph g> (. Graph g1;g=new Graph(); .) = ident (. Symbol s=Symbol.Find(t.val); Node n; if(s!=null) n= new Node(s); else n=new Node(new Symbol(Node.t,t.val)); //type could be nt, but not known yet g=new Graph(n); .) | terminal (. char[] trim=new char[1]; trim[0]=t.val[0]; String temp=t.val.Trim(trim); Node n =new Node(new Symbol(Node.t,temp)); g=new Graph(n); .) | wrap (. Node n =new Node(Node.wrap,null); g=new Graph(n); .) | '(' Expr <out g1>')' (. g=g1; .) | '[' Expr <out g1>']' (. Graph.MakeOption(g1); g=g1; .) | '{' Expr <out g1>'}' (. Graph.MakeIteration(g1); g=g1; .) . END EBNF.