options { STATIC = false; } PARSER_BEGIN(Parser) import demeter.*; public class Parser { // oit is uugly. Why isn't there a Character.valueOf(String)? static char unescapifyChar(String s) { char c = s.charAt(0); if (c == '\\') { switch (s.charAt(1)) { case 'n': c = '\n'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'r': c = '\r'; break; case 'f': c = '\f'; break; case '\\': c = '\\'; break; case '\'': c = '\''; break; case '\"': c = '\"'; break; default: c = (char) Integer.parseInt(s.substring(2, s.length()), 8); break; } } return c; } // Even uglier... static String unescapify(String s) { char str[] = new char[s.length()]; int i = 0, o = 0; while (i < s.length()) { char c = s.charAt(i++); if (c == '\\') { int j = i + 1; while (j < s.length() && Character.digit(s.charAt(j), 8) != -1) { j++; } c = unescapifyChar(s.substring(i-1, j)); i = j; } str[o++] = c; } return String.valueOf(str, 0, o); } } PARSER_END(Parser) Cd_graph Cd_graph() : { Cd_graph it; Adj _first; Adj_list _rest; } { { it=new Cd_graph(); } _first=Adj() { it.set_first(_first); } _rest=Adj_list() { it.set_rest(_rest); } { return it; } } Adj Adj() : { Adj it; Vertex _vertex; Neighbors _ns; } { { it=new Adj(); } _vertex=Vertex() { it.set_vertex(_vertex); } _ns=Neighbors() { it.set_ns(_ns); } "." { return it; } } Neighbors Neighbors() : { Neighbors it; } { ( it=Construct() | it=Alternat() ) { return it; } } Construct Construct() : { Construct it; Any_vertex_list _c_ns; } { { it=new Construct(); } "=" _c_ns=Any_vertex_list() { it.set_c_ns(_c_ns); } { return it; } } Alternat Alternat() : { Alternat it; Vertex _first; Vertex _second; } { { it=new Alternat(); } ":" _first=Vertex() { it.set_first(_first); } "|" _second=Vertex() { it.set_second(_second); } { return it; } } Any_vertex Any_vertex() : { Any_vertex it; } { ( it=Labeled_vertex() | it=Syntax_vertex() ) { return it; } } Syntax_vertex Syntax_vertex() : { Syntax_vertex it; String _string; } { { it=new Syntax_vertex(); } _string=String() { it.set_string(_string); } { return it; } } Labeled_vertex Labeled_vertex() : { Labeled_vertex it; Ident _label_name; Vertex _class_name; } { { it=new Labeled_vertex(); } "<" _label_name=Ident() { it.set_label_name(_label_name); } ">" _class_name=Vertex() { it.set_class_name(_class_name); } { return it; } } Adj_list Adj_list() : { Adj_list it; } { ( it=Cd_graph() | it=Empty_cd_graph() ) { return it; } } Any_vertex_list Any_vertex_list() : { Any_vertex_list it; } { ( it=Nany_vertex_list() | it=Empty() ) { return it; } } Nany_vertex_list Nany_vertex_list() : { Nany_vertex_list it; Any_vertex _first; Any_vertex_list _rest; } { { it=new Nany_vertex_list(); } _first=Any_vertex() { it.set_first(_first); } _rest=Any_vertex_list() { it.set_rest(_rest); } { return it; } } Empty Empty() : { Empty it; } { { it=new Empty(); } { return it; } } Empty_cd_graph Empty_cd_graph() : { Empty_cd_graph it; } { { it=new Empty_cd_graph(); } { return it; } } Vertex Vertex() : { Vertex it; Ident _name; } { { it=new Vertex(); } _name=Ident() { it.set_name(_name); } { return it; } } CountingVisitor CountingVisitor() : { CountingVisitor it; Integer _total; } { { it=new CountingVisitor(); } _total=Integer() { it.set_total(_total); } { return it; } } Main Main() : { Main it; } { { it=new Main(); } { return it; } } Ident Ident() : { Token t; } { t= { return new Ident(t.image); } } String String() : { Token t; } { t= { String s = t.image; return unescapify(s.substring(1, s.length()-1)); } } Text Text() : { Token t; } { t= { String s = t.image; return new Text(s.substring(2, s.length()-2)); } } Number Number() : { Token t; String s; int radix; Number num; } { ( ( t= { s = t.image; radix = 10; } | t= { // Strip off the "0x". s = t.image.substring(2, t.image.length()); radix = 16; } | t= { s = t.image; radix = 8; } ) { switch (s.charAt(s.length()-1)) { case 'l': case 'L': num = Long.valueOf(s.substring(0, s.length()-1), radix); break; default: num = Integer.valueOf(s, radix); break; } } | t= { s = t.image; switch (s.charAt(s.length()-1)) { case 'd': case 'D': num = Double.valueOf(s.substring(0, s.length()-1)); break; case 'f': case 'F': num = Float.valueOf(s.substring(0, s.length()-1)); break; default: num = Float.valueOf(s); break; } } ) { return num; } } Integer Integer() : { Number num; } { num=Number() { return new Integer(num.intValue()); } } Long Long() : { Number num; } { num=Number() { return new Long(num.longValue()); } } Float Float() : { Number num; } { num=Number() { return new Float(num.floatValue()); } } Double Double() : { Number num; } { num=Number() { return new Double(num.doubleValue()); } } // Lexical specification (largely taken from Java.jack): IGNORE_IN_BNF : {} { " " | "\t" | "\n" | "\r" | <"//" (~["\n","\r"])* ("\n"|"\r\n")> | <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> } TOKEN : /* LITERALS */ {} { < DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* (["l","L"])? > | < HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ (["l","L"])? > | < OCTAL_LITERAL: "0" (["0"-"7"])* (["l","L"])? > | < FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])+ ()? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"] > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < CHARACTER_LITERAL: "'" ( (~["'","\\","\n","\r"]) | ("\\" ( ["n","t","b","r","f","\\","'","\""] | ["0"-"7"] ( ["0"-"7"] )? | ["0"-"3"] ["0"-"7"] ["0"-"7"] ) ) ) "'" > | < STRING_LITERAL: "\"" ( (~["\"","\\","\n","\r"]) | ("\\" ( ["n","t","b","r","f","\\","'","\""] | ["0"-"7"] ( ["0"-"7"] )? | ["0"-"3"] ["0"-"7"] ["0"-"7"] ) ) )* "\"" > | < TEXT_LITERAL: "(@" (~["@"])* ( "@" ~[")"] (~["@"])* )* "@)" > } TOKEN : /* IDENTIFIERS */ {} { < IDENTIFIER: (|)* > | < #LETTER: [ "\u0024", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a", "\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u00ff", "\u0100"-"\u1fff", "\u3040"-"\u318f", "\u3300"-"\u337f", "\u3400"-"\u3d2d", "\u4e00"-"\u9fff", "\uf900"-"\ufaff" ] > | < #DIGIT: [ "\u0030"-"\u0039", "\u0660"-"\u0669", "\u06f0"-"\u06f9", "\u0966"-"\u096f", "\u09e6"-"\u09ef", "\u0a66"-"\u0a6f", "\u0ae6"-"\u0aef", "\u0b66"-"\u0b6f", "\u0be7"-"\u0bef", "\u0c66"-"\u0c6f", "\u0ce6"-"\u0cef", "\u0d66"-"\u0d6f", "\u0e50"-"\u0e59", "\u0ed0"-"\u0ed9", "\u1040"-"\u1049" ] > }