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* '*'+)* '/'; a = ['a' + 'A']; b = ['b' + 'B']; c = ['c' + 'C']; d = ['d' + 'D']; e = ['e' + 'E']; f = ['f' + 'F']; g = ['g' + 'G']; h = ['h' + 'H']; i = ['i' + 'I']; j = ['j' + 'J']; k = ['k' + 'K']; l = ['l' + 'L']; m = ['m' + 'M']; n = ['n' + 'N']; o = ['o' + 'O']; p = ['p' + 'P']; q = ['q' + 'Q']; r = ['r' + 'R']; s = ['s' + 'S']; t = ['t' + 'T']; u = ['u' + 'U']; v = ['v' + 'V']; w = ['w' + 'W']; x = ['x' + 'X']; y = ['y' + 'Y']; z = ['z' + 'Z']; 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 = f o r e a c h; for = f o r; each = e a c h; in = i n; reversed = r e v e r s e d; if = i f; else = e l s e; global = g l o b a l; switch = s w i t c h; case = c a s e; default = d e f a u l t; return = r e t u r n; procedure = p r o c e d u r e; function = f u n c t i o n; true = t r u e; false = f a l s e; 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_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_or_function {-> P.procedure P.function} = {procedure} P.procedure {-> P.procedure Null } | {function} P.function {-> Null P.function }; procedure = T.procedure ident l_par param_list? r_par l_brace stmt* r_brace {-> New procedure(ident, [param_list.ident], New stmts([stmt])) }; //*** T.function ident l_par param_list? r_par l_brace stmt* P.return r_brace {-> New function(ident, [param_list.ident], New stmts([stmt]), return.exp) } function = T.function ident l_par param_list? r_par l_brace stmt* P.return r_brace {-> New function(ident, [param_list.ident], New stmts([stmt]), P.return.exp) }; return {-> exp } = T.return exp semi_colon {-> exp }; //*** param_list {-> ident+ } = 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} for_each ident in reversed? exp stmt_brace {-> New stmt.foreach(ident, in, reversed, exp, New stmts([stmt_brace.stmt])) } | {if} if l_par exp r_par stmt_brace else_part? {-> New stmt.if(l_par, exp, New stmts([stmt_brace.stmt]), New stmts([else_part.stmt])) } | {call} call semi_colon {-> New stmt.call(call.ident, call.l_par, [call.exp]) } | {switch} switch l_par exp r_par case_brace {-> New stmt.switch(exp, [case_brace.case], case_brace.default) }; for_each {-> } = {for} for each {-> } | {foreach} foreach {-> }; 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_brace {-> P.case* P.default } = l_brace P.case+ P.default? r_brace {-> [P.case] P.default }; case = T.case string_literal additional_string_literal* colon stmt_brace {-> New case([string_literal, additional_string_literal.string_literal], New stmts([stmt_brace.stmt])) }; additional_string_literal {-> string_literal } = comma string_literal {-> string_literal }; default = T.default colon stmt_brace {-> New default(New stmts([stmt_brace.stmt])) }; exp = {or} exp or and_exp {-> New exp.or(exp, or, and_exp.exp) } | {and} and_exp {-> and_exp.exp }; and_exp {-> exp } = {and} and_exp and compare_exp {-> New exp.and(and_exp.exp, and, 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, gt, r_add_exp.exp) } | {ge} [l_add_exp]:add_exp ge [r_add_exp]:add_exp {-> New exp.ge(l_add_exp.exp, ge, r_add_exp.exp) } | {eq} [l_add_exp]:add_exp eq [r_add_exp]:add_exp {-> New exp.eq(l_add_exp.exp, eq, r_add_exp.exp) } | {ne} [l_add_exp]:add_exp ne [r_add_exp]:add_exp {-> New exp.ne(l_add_exp.exp, ne, r_add_exp.exp) } | {le} [l_add_exp]:add_exp le [r_add_exp]:add_exp {-> New exp.le(l_add_exp.exp, le, r_add_exp.exp) } | {lt} [l_add_exp]:add_exp lt [r_add_exp]:add_exp {-> New exp.lt(l_add_exp.exp, lt, 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, plus, mult_exp.exp) } | {minus} add_exp minus mult_exp {-> New exp.minus(add_exp.exp, minus, 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, mult, l_unary_exp.exp) } | {div} mult_exp div l_unary_exp {-> New exp.div(mult_exp.exp, div, l_unary_exp.exp) } | {mod} mult_exp mod l_unary_exp {-> New exp.mod(mult_exp.exp, mod, 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(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, dot, ident) } | {base} base_exp {-> base_exp.exp}; base_exp {-> exp } = {string} string_literal {-> New exp.string(T.string_literal) } | {number} number {-> New exp.number(number) } | {true} true {-> New exp.true() } | {false} false {-> New exp.false() } | {ident} ident {-> New exp.ident(ident) } | {par} l_par exp r_par {-> exp} | {call} call {-> New exp.call(call.ident, call.l_par, [call.exp]) }; call {-> ident l_par exp* } = ident l_par arg_list? r_par {-> ident l_par [arg_list.exp] }; //*** 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; function = [name]:ident [params]:ident* stmts [return]:exp; stmt = {assign} [var]:ident exp | {global_assign} [var]:ident exp | {foreach} [var]:ident in reversed? exp stmts | {if} l_par exp [then_stmts]:stmts [else_stmts]:stmts | {call} [proc_name]:ident l_par [args]:exp* | {switch} exp [cases]:P.case+ P.default?; case = [string_literals]:string_literal+ [stmts]:stmts; default = [stmts]:stmts; stmts = stmt*; exp = {or} [l_exp]:exp or [r_exp]:exp | {and} [l_exp]:exp and [r_exp]:exp | {gt} [l_exp]:exp gt [r_exp]:exp | {ge} [l_exp]:exp ge [r_exp]:exp | {eq} [l_exp]:exp eq [r_exp]:exp | {ne} [l_exp]:exp ne [r_exp]:exp | {le} [l_exp]:exp le [r_exp]:exp | {lt} [l_exp]:exp lt [r_exp]:exp | {plus} [l_exp]:exp plus [r_exp]:exp | {minus} [l_exp]:exp minus [r_exp]:exp | {mult} [l_exp]:exp mult [r_exp]:exp | {div} [l_exp]:exp div [r_exp]:exp | {mod} [l_exp]:exp mod [r_exp]:exp | {not} not exp | {dot} exp dot ident | {string} string_literal | {number} number | {true} | {false} | {ident} ident | {call} [func_name]:ident l_par [args]:exp*;