Package minijava; Helpers lf = 10 ; // linefeed cr = 13 ; // carriage return tab = 09 ; space = ' ' ; all_input_chars = [0..0xffff] ; letter = ['a'.. 'z'] | ['A'..'Z']; digit = ['0'..'9']; input_chars = [all_input_chars - [cr + lf]]; line_terminator = lf | cr | cr lf; States normal, comment; Tokens {normal} clas = 'class' ; {normal} public = 'public' ; {normal} static = 'static' ; {normal} void = 'void' ; {normal} main = 'main' ; {normal} string = 'String' ; {normal} extends = 'extends' ; {normal} return = 'return' ; {normal} int = 'int' ; {normal} boolean = 'boolean' ; {normal} if = 'if' ; {normal} else = 'else' ; {normal} while = 'while' ; {normal} println = 'System.out.println' ; {normal} length = 'length' ; {normal} true = 'true' ; {normal} false = 'false' ; {normal} this = 'this' ; {normal} new = 'new' ; {normal} assign = '=' ; {normal} dot = '.' ; {normal} comma = ',' ; {normal} semicol = ';' ; {normal} lparen = '(' ; {normal} rparen = ')' ; {normal} lbrack = '[' ; {normal} rbrack = ']' ; {normal} lbrace = '{' ; {normal} rbrace = '}' ; {normal} exclam = '!' ; {normal} and = '&&' ; {normal} lt = '<' ; {normal} plus = '+' ; {normal} minus = '-' ; {normal} times = '*' ; {normal} whitespace = (space | tab | line_terminator)* ; {normal} id_literal = letter ( letter | digit | '_' )* ; {normal} integer = digit+ ; {normal} comment_endofline = '//' input_chars* line_terminator ; {normal->comment, comment} comment = '/*'; {comment} comment_star = '*'; {comment} comment_slash = '/'; {comment} comment_body = [all_input_chars-['*' + '/']]*; Ignored Tokens comment, comment_endofline, whitespace; Productions program = main_class class_decl* {-> New program( main_class, [class_decl] ) }; main_class = clas [clname]:identifier lbrace public static void main lparen string lbrack rbrack [arg]:identifier rparen [left]:lbrace statement rbrace [right]:rbrace {-> New main_class(clname, arg, statement ) }; class_decl = {simple} clas identifier lbrace var_decl* method_decl* rbrace {-> New class_decl.simple(identifier, [var_decl], [method_decl]) } | {extends} clas [newcl]:identifier extends [oldcl]:identifier lbrace var_decl* method_decl* rbrace {-> New class_decl.extends(newcl, oldcl, [var_decl], [method_decl] ) } ; var_decl = type identifier semicol {-> New var_decl(type, identifier) } ; method_decl = public type identifier lparen formal_list? rparen lbrace var_decl* statement* return exp semicol rbrace {-> New method_decl(type, identifier, [formal_list.formal], [var_decl], [statement], exp) } ; formal_list {-> formal*} = formal formal_list_tail* {-> [formal formal_list_tail.formal]}; formal_list_tail {-> formal } = comma formal {-> formal } ; formal = type identifier {-> New formal(type, identifier) } ; type = {int_array} int lbrack rbrack {-> New type.int_array() } | {boolean} boolean {-> New type.boolean() } | {integer} int {-> New type.integer() } | {identifier} id_literal {-> New type.identifier(id_literal) } ; statement = {block} lbrace statement* rbrace {-> New statement.block( [statement] ) } | {if} if lparen exp rparen [ifpart]: statement else [elsepart]: statement {-> New statement.if(exp, ifpart, elsepart) } | {while} while lparen exp rparen statement {-> New statement.while(exp,statement) } | {print} println lparen exp rparen semicol {-> New statement.print(exp) } | {assign} identifier assign exp semicol {-> New statement.assign(identifier,exp) } | {array_assign} identifier lbrack [index]: exp rbrack assign [rhs]: exp semicol {-> New statement.array_assign(identifier, index, rhs) } ; exp = {and} and_exp {-> and_exp.exp } ; and_exp {-> exp } = {condit} [left]:and_exp and [right]:lt_exp {-> New exp.and(left.exp, right.exp) } | {lt_exp} lt_exp {-> lt_exp.exp } ; lt_exp {-> exp } = [left]:lt_exp lt [right]:add_exp {-> New exp.less_than(left.exp, right.exp) } | {add_exp} add_exp {-> add_exp.exp } ; add_exp {-> exp } = {plus} [left]:add_exp plus [right]:mult_exp {-> New exp.plus(left.exp, right.exp) } | {minus} [left]:add_exp minus [right]:mult_exp {-> New exp.minus(left.exp, right.exp) } | {times} mult_exp {-> mult_exp.exp } ; mult_exp {-> exp } = [left]:mult_exp times [right]:not {-> New exp.times(left.exp, right.exp) } | {unary} not {-> not.exp } ; not {-> exp } = {not} exclam postfix {-> New exp.not(postfix.exp) } | {postfix} postfix {-> postfix.exp } ; postfix {-> exp } = {name} id_literal {-> New exp.identifier(id_literal) } | {primary} primary {-> primary.exp } ; primary {-> exp } = {no_new_array} primary_no_new_array {-> primary_no_new_array.exp } | {array_creation} new int lbrack exp rbrack {-> New exp.new_array(exp) } ; primary_no_new_array {-> exp } = {true} true {-> New exp.true() } | {false} false {-> New exp.false() } | {integer} integer {-> New exp.integer_literal(integer) } | {this} this {-> New exp.this() } | {parens} lparen exp rparen {-> exp.exp } | {array_lookup} postfix lbrack [index]: exp rbrack {-> New exp.array_lookup(postfix.exp, index.exp)} | {class_instance_creation} new identifier lparen rparen {-> New exp.new_object(identifier) } | {method_invoc} postfix dot identifier lparen exp_list? rparen {-> New exp.call(postfix.exp, identifier, [exp_list.exp] ) } | {length} postfix dot length {-> New exp.array_length(postfix.exp) } ; exp_list {-> exp*} = exp exp_list_tail* {-> [exp exp_list_tail.exp]} ; exp_list_tail {-> exp } = comma exp {-> exp } ; identifier = id_literal {-> New identifier(id_literal) }; Abstract Syntax Tree program = main_class class_decl* ; main_class = [clname]:identifier [arg]:identifier statement ; class_decl = {simple} identifier var_decl* method_decl* | {extends} [newcl]:identifier [oldcl]: identifier var_decl* method_decl* ; var_decl = type identifier ; method_decl = type identifier formal* var_decl* statement* exp ; formal = type identifier ; type = {int_array} | {boolean} | {integer} | {identifier} id_literal ; statement = {block} statement* | {if} exp [ifpart]: statement [elsepart]: statement | {while} exp statement | {print} exp | {assign} identifier exp | {array_assign} identifier [index]: exp [rhs]:exp ; exp = {and} [left]:exp [right]:exp | {less_than} [left]:exp [right]:exp | {plus} [left]:exp [right]:exp | {minus} [left]:exp [right]:exp | {times} [left]:exp [right]:exp | {array_lookup} exp [index]:exp | {array_length} exp | {call} exp identifier [args]:exp* | {integer_literal} integer | {true} | {false} | {identifier} id_literal | {this} | {new_array} exp | {new_object} identifier | {not} exp ; identifier = id_literal ;