// // mjava.grammar // To build: // java -jar sablecc.jar mjava.grammar // javac Main.java // Helpers digit = ['0'..'9']; let = ['a'..'z'] | ['A'..'Z']; space = ' ' | 9; newline = 10 | 11 | 12; not_star = [0..41] | [43..127]; not_slash = [0..46] | [48..127]; not_slashstar = [0..41] | [43..46] | [48..127]; not_newline = [0..9] | [11..127]; Tokens // TODO: add missing tokens according to Appendix A and B boolean = 'boolean'; class_token = 'class'; // must not be "class" - that conflicts with Java keywords else = 'else'; extends = 'extends'; false = 'false'; if = 'if'; int = 'int'; length = 'length'; main = 'main'; new = 'new'; println = 'System.out.println'; public = 'public'; return = 'return'; static = 'static'; string = 'String'; this = 'this'; true = 'true'; void = 'void'; while = 'while'; lbracket = '['; rbracket = ']'; lbrace = '{'; rbrace = '}'; lparen = '('; rparen = ')'; semi = ';'; equal = '='; dot = '.'; bang = '!'; comma = ','; plus = '+'; and = '&&'; less = '<'; minus = '-'; star = '*'; // TODO: complete the following to define tokens for identifiers, numbers, // whitespace, single-line comments starting with '//', and multi-line // comments starting with /* and ending with */ id = let; number = digit; whitespace = (space | newline)*; line_comment = '//' newline ; slashstar_comment = '/*' ; Ignored Tokens whitespace, line_comment, slashstar_comment; Productions program = main_class class_decl* ; main_class = class_token id lbrace main_def rbrace ; main_def = public static void main lparen string lbracket rbracket id rparen lbrace statement rbrace ; class_decl = {baseclass} class_token id lbrace var_decl* method_decl* rbrace | {extclass} class_token [classid]:id extends [baseid]:id lbrace var_decl* method_decl* rbrace ; var_decl = type id semi ; method_decl = public type id lparen formal_list rparen method_body ; method_body = lbrace var_decl* statement* return exp semi rbrace ; formal_list = {empty} | {nonempty} type id formal_rest ; formal_rest = {empty} | {nonempty} comma type id formal_rest ; type = {array} int lbracket rbracket | {bool} boolean | {int} int | {class} id ; statement = {ifone} if lparen exp rparen statement | {if} if lparen exp rparen [truepart]:stmt_all_paired else [falsepart]:statement | {while} while lparen exp rparen statement | {simple} simple_stmt ; simple_stmt = {print} println lparen exp rparen semi | {assign} id equal exp semi | {array} id lbracket [index]:exp rbracket equal exp semi | {nested} lbrace statement* rbrace ; stmt_all_paired= {sans_trailer} simple_stmt | {while} while lparen exp rparen stmt_all_paired | {if} if lparen exp rparen [truepart]:stmt_all_paired else [falsepart]:stmt_all_paired ; exp = and_exp ; and_exp = {simple} comparison | {and} [left]:and_exp and [right]:comparison ; comparison = {simple} arith_exp | {compare} [left]:arith_exp less [right]:arith_exp ; arith_exp = {simple} term | {add} [left]:arith_exp plus [right]:term | {subt} [left]:arith_exp minus [right]:term ; term = {simple} bool_exp | {times} [left]:term star [right]:bool_exp ; bool_exp = {simple} factor | {not} bang bool_exp ; factor = {array} factor lbracket [index]:exp rbracket | {length} factor dot length | {call} factor dot id lparen exp_list rparen | {num} number | {true} true | {false} false | {id} id | {this} this | {newarray} new int lbracket exp rbracket | {newobj} new id lparen rparen | {nested} lparen exp rparen ; exp_list = {empty} | {exps} exp exp_rest ; exp_rest = {empty} | {exps} comma exp exp_rest ;