Package org.sablecc.sablecc.script; Helpers all = [0 .. 0xffff]; letter = [['a'..'z']+['A'..'Z']]; digit = ['0'..'9']; cr = 13; lf = 10; tab = 9; eol = cr | lf | cr lf; not_cr_lf = [all - [cr + lf]]; string_char = [not_cr_lf - '"']; not_star = [all - '*']; not_star_slash = [not_star - '/']; line_comment = '//' not_cr_lf* eol?; long_comment = '/*' not_star* '*'+ (not_star_slash not_star* '*'+)* '/'; Tokens assign = '='; l_par = '('; r_par = ')'; colon = ':'; semi_colon = ';'; l_brace = '{'; r_brace = '}'; dot = '.'; not = '!'; plus = '+'; comma = ','; mult = '*'; div = '/'; minus = '-'; mod = '%'; and = '&&'; or = '||'; gt = '>'; ge = '>='; eq = '=='; ne = '!='; le = '<='; lt = '<'; foreach = 'foreach'; in = 'in'; reversed = 'reversed'; if = 'if'; else = 'else'; global = 'global'; switch = 'switch'; case = 'case'; default = 'default'; return = 'return'; procedure = 'procedure'; function = 'function'; string_literal = '"' (string_char | '""')* '"'; ident = letter (letter | digit)*; number = digit+; blank = (' ' | cr | lf | tab | line_comment | long_comment)+; Ignored Tokens blank; Productions script = global_declarations? procedure_or_function+ {-> New script([global_declarations.ident], [procedure_or_function.procedure], [procedure_or_function.function]) } ; global_declarations {-> ident* } = global ident_list? semi_colon {-> [ident_list.ident] }; ident_list {-> ident+ } = ident ident_list_tail* {-> [ident, ident_list_tail.ident] }; ident_list_tail {-> ident} = comma ident {-> ident}; procedure_or_function {-> P.procedure? P.function?} = {procedure} P.procedure {-> procedure Null } | {function} P.function {-> Null function }; procedure = T.procedure ident l_par param_list? r_par l_brace stmt* r_brace {-> New procedure(ident, [param_list.ident], [stmt]) }; function = T.function ident l_par param_list? r_par l_brace stmt* P.return r_brace {-> New function(ident, [param_list.ident], [stmt], return.exp) }; return {-> exp } = T.return exp semi_colon {-> exp }; param_list {-> ident+ } = ident param_list_tail* {-> [ident, param_list_tail.ident] }; param_list_tail {-> ident } = comma ident {-> ident }; stmt = {assign} ident assign exp semi_colon {-> New stmt.assign(ident, exp) } | {global_assing} global ident assign exp semi_colon {-> New stmt.global_assign(ident, exp) } | {foreach} foreach ident in reversed? exp stmt_brace {-> New stmt.foreach(ident, reversed, exp) } | {if} if l_par exp r_par stmt_brace else_part? {-> New stmt.if(exp, [stmt_brace.stmt], [else_part.stmt]) } | {call} call semi_colon {-> New stmt.call(call.ident, [call.exp]) } | {switch} switch l_par exp r_par case_brace {-> New stmt.switch(exp, [case_brace.case], case_brace.default) }; stmt_brace {-> stmt* } = l_brace stmt* r_brace {-> [stmt] }; else_part {-> stmt* } = else stmt_brace {-> [stmt_brace.stmt] }; case_brace {-> P.case+ P.default? } = l_brace P.case+ P.default? r_brace {-> [case] default }; case = T.case string_literal additional_string_literal* colon stmt_brace {-> New case([string_literal, additional_string_literal.string_literal], [stmt_brace.stmt]) }; additional_string_literal {-> string_literal } = comma string_literal {-> string_literal }; default = T.default colon stmt_brace {-> New default([stmt_brace.stmt]) }; exp = {or} exp or and_exp {-> New exp.or(exp, and_exp.exp) } | {and} and_exp {-> and_exp.exp }; and_exp {-> exp } = {and} and_exp and compare_exp {-> New exp.and(and_exp.exp, compare_exp.exp) } | {compare} compare_exp {-> compare_exp.exp }; compare_exp {-> exp } = {gt} [l_add_exp]:add_exp gt [r_add_exp]:add_exp {-> New exp.gt(l_add_exp.exp, r_add_exp.exp) } | {ge} [l_add_exp]:add_exp ge [r_add_exp]:add_exp {-> New exp.ge(l_add_exp.exp, r_add_exp.exp) } | {eq} [l_add_exp]:add_exp eq [r_add_exp]:add_exp {-> New exp.eq(l_add_exp.exp, r_add_exp.exp) } | {ne} [l_add_exp]:add_exp ne [r_add_exp]:add_exp {-> New exp.ne(l_add_exp.exp, r_add_exp.exp) } | {le} [l_add_exp]:add_exp le [r_add_exp]:add_exp {-> New exp.le(l_add_exp.exp, r_add_exp.exp) } | {lt} [l_add_exp]:add_exp lt [r_add_exp]:add_exp {-> New exp.lt(l_add_exp.exp, r_add_exp.exp) } | {add} add_exp {-> add_exp.exp }; add_exp {-> exp } = {plus} add_exp plus mult_exp {-> New exp.plus(add_exp.exp, mult_exp.exp) } | {minus} add_exp minus mult_exp {-> New exp.minus(add_exp.exp, mult_exp.exp) } | {mult} mult_exp {-> mult_exp.exp }; mult_exp {-> exp } = {mult} mult_exp mult l_unary_exp {-> New exp.mult(mult_exp.exp, l_unary_exp.exp) } | {div} mult_exp div l_unary_exp {-> New exp.div(mult_exp.exp, l_unary_exp.exp) } | {mod} mult_exp mod l_unary_exp {-> New exp.mod(mult_exp.exp, l_unary_exp.exp) } | {l_unary} l_unary_exp {-> l_unary_exp.exp }; l_unary_exp {-> exp } = {not} not l_unary_exp {-> New exp.not(l_unary_exp.exp) } | {r_unary_exp} r_unary_exp {-> r_unary_exp.exp}; r_unary_exp {-> exp } = {dot} r_unary_exp dot ident {-> New exp.dot(r_unary_exp.exp, ident) } | {base} base_exp {-> base_exp.exp}; base_exp {-> exp } = {string} string_literal {-> New exp.string(string_literal) } | {number} number {-> New exp.number(number) } | {ident} ident {-> New exp.ident(ident) } | {par} l_par exp r_par {-> exp} | {call} call {-> New exp.call(call.ident, [call.exp]) }; call {-> ident exp* } = ident l_par arg_list? r_par {-> ident [arg_list.exp] }; arg_list {-> exp+ } = exp arg_list_tail* {-> [exp, arg_list_tail.exp] }; arg_list_tail {-> exp } = comma exp {-> exp }; Abstract Syntax Tree script = [globals]:ident* [procedures]:P.procedure* [functions]:P.function*; procedure = [name]:ident [params]:ident* [stmts]:stmt*; function = [name]:ident [params]:ident* [stmts]:stmt* [return]:exp; stmt = {assign} [var]:ident exp | {global_assign} [var]:ident exp | {foreach} [var]:ident reversed? exp | {if} exp [then_stmts]:stmt* [else_stmts]:stmt* | {call} [proc_name]:ident [args]:exp* | {switch} exp [cases]:P.case+ P.default?; case = [string_literals]:string_literal+ [stmts]:stmt*; default = [stmts]:stmt*; exp = {or} [l_exp]:exp [r_exp]:exp | {and} [l_exp]:exp [r_exp]:exp | {gt} [l_exp]:exp [r_exp]:exp | {ge} [l_exp]:exp [r_exp]:exp | {eq} [l_exp]:exp [r_exp]:exp | {ne} [l_exp]:exp [r_exp]:exp | {le} [l_exp]:exp [r_exp]:exp | {lt} [l_exp]:exp [r_exp]:exp | {plus} [l_exp]:exp [r_exp]:exp | {minus} [l_exp]:exp [r_exp]:exp | {mult} [l_exp]:exp [r_exp]:exp | {div} [l_exp]:exp [r_exp]:exp | {mod} [l_exp]:exp [r_exp]:exp | {not} exp | {dot} exp ident | {string} string_literal | {number} number | {ident} ident | {call} [func_name]:ident [args]:exp*;