options{ STATIC = false; } PARSER_BEGIN(TheParser) // No namespace needed here... but it's possible // namespace myNameSpace; using System; using System.IO; // A few nested classes to make things simpler class TheParser{ public static void Main(String[] args){ Console.WriteLine(new TheParser(new StringReader("1 2 3 4 5")) .parse_MainC()); } // A Simple top-level class public class MainC{ public L lst; public MainC(L l){ lst = l; } public override String ToString(){ return "MainC: ("+lst+")"; } } // (L)ists public abstract class L{ public abstract bool isEmpty(); } // (E)mpty Lists public class E : L{ public override String ToString(){ return ""; } public override bool isEmpty(){ return true; } } // (C)ons Lists public class C : L{ public int f; public L r; public C(int ff, L rr){ f = ff; r = rr; } public override bool isEmpty(){ return false; } public override String ToString(){ return f+(r.isEmpty()?"":", ")+r; } } } PARSER_END(TheParser) // So we don't have to deal with tokens... int parse_int():{ Token t; }{ t = <INT> { return Int32.Parse(t.image); } } // Parse a MainC public MainC parse_MainC():{ L lst; }{ lst = parse_L() { return new MainC(lst); } } // Parse a Cons/Empty List public L parse_L():{ L sup; }{ ( sup = parse_C() { return sup; } | sup = parse_E() { return sup; } ) } // Non-empty List public C parse_C():{ int f; L r; }{ f = parse_int() r = parse_L() { return new C(f,r); } } // Empty List public E parse_E():{ }{ { return new E(); } } // Lexer Definitions SKIP : { " " | "\t" | "\n" | "\r" | "\r\n" } SKIP : { <"//" (~["\n","\r"])* ("\n" | "\r\n")> } SKIP : { <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/">} TOKEN: { < INT : ("+" | "-")?(["0"-"9"])+ > }