Package ee.mare.indrek.sablecc.xss; Helpers letter = ['A'..'Z'] | ['a'..'z'] | [0x7F .. 0xFF]; digit = ['0'..'9']; nondigit = '_' | letter; sign = '+' | '-'; digit_seq = digit+; letter_seq = letter+; nondigit_seq = nondigit+; identifier = nondigit (digit | nondigit)*; all = [0 .. 0xFFFF]; cr = 13; lf = 10; tab = 9; eol = cr | lf | cr lf; blank = (eol | tab | ' '); 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']; States data, code; Tokens {data} data_comment = '[-!' ([all - '!'] | '!' [all - '-'] | '!-' [all - ']'])* '!-]'; {data->code} cmd_start = '[-'; {code->data} cmd_end = '-]'; {code} foreach = f o r e a c h; {code} reverse_foreach = r e v e r s e '_' f o r e a c h; {code} if = i f; {code} else = e l s e; {code} choose = c h o o s e; {code} when = w h e n; {code} end = e n d; {code} include = i n c l u d e; {code} in = i n; {code} ecmascript = e c m a s c r i p t; {code} otherwise = o t h e r w i s e; {code} set = s e t; {code} param = p a r a m; {code} output = o u t p u t; {code} template = t e m p l a t e; {code} call = c a l l; {code} sep = s e p; {code} print = p r i n t; {code} equals = '='; {code} l_par = '('; {code} r_par = ')'; {code} comma = ','; {code} plus = '+'; {data} data = ([all - ['[' + ['$' + '@']]] | '['+ [all - ['-' + ['@' + '$']]] |'['+ '--' | '$$' | '@@')+ | '['; {data} ixpath = '${' ([all - ['{' + '}']] | '{{' | '}}')* '}'; {code, data} iattrib = '@' identifier | '@{' identifier '}'; {code, data} ivar = '$' identifier; {code} blank = blank+; {code} identifier = identifier; {code} xpath = '{' ([all - ['{' + '}']] | '{{' | '}}')* '}'; {code} literal = '"' ([all - '"'] | '""')* '"' | ''' ([all - '''] | ''' ''')* '''; // ' {code} comment = '//' [all - [cr + lf]]* eol; Ignored Tokens blank, comment, data_comment; Productions script {-> script} = statement* {-> New script([statement.statement]) } ; statement {-> statement} = {empty} cmd_start cmd_end {-> Null } | {data} data {-> New statement.data(data) } | {foreach} [cs1]:cmd_start [fe1]:foreach foreach_arg? xpath [ce1]:cmd_end statement* [cs2]:cmd_start end [fe2]:foreach? [ce2]:cmd_end {-> New statement.foreach (foreach_arg.identifier, xpath, [statement.statement]) } | {reverse_foreach} [cs1]:cmd_start [fe1]:reverse_foreach foreach_arg? xpath [ce1]:cmd_end statement* [cs2]:cmd_start end [fe2]:reverse_foreach? [ce2]:cmd_end {-> New statement.reverse_foreach (foreach_arg.identifier, xpath, [statement.statement]) } | {include} cmd_start include literal cmd_end {-> New statement.include (literal) } | {ecmascript} [cs1]:cmd_start [e1]:ecmascript [ce1]:cmd_end data [cs2]:cmd_start end [e2]:ecmascript? [ce2]:cmd_end {-> New statement.ecmascript(data) } | {choose} [cs1]:cmd_start [c1]:choose [ce1]:cmd_end choose_when* choose_otherwise? data? [cs2]:cmd_start end [c2]:choose? [ce2]:cmd_end {-> New statement.choose ([choose_when.choose_when], [choose_otherwise.otherwise]) } | {set} cmd_start set arg_list cmd_end {-> New statement.set([arg_list.arg]) } | {param} cmd_start param oarg_list cmd_end {-> New statement.param([oarg_list.oarg]) } | {output} [cs1]:cmd_start output expr [ce1]:cmd_end statement* [cs2]:cmd_start end [o2]:output? [ce2]:cmd_end {-> New statement.output (expr, [statement]) } | {ixpath} ixpath {->New statement.print(New expr.ixpath(ixpath)) } | {iattrib} iattrib {->New statement.print(New expr.iattrib(iattrib)) } | {ivar} ivar {->New statement.print(New expr.ivar(ivar)) } | {template} [cs1]:cmd_start [t1]:template identifier l_par oarg_list? r_par [ce1]:cmd_end statement* [cs2]:cmd_start end [t2]:template? [ce2]:cmd_end {-> New statement.template (identifier, [oarg_list.oarg], [statement]) } | {call} [cs1]:cmd_start [c1]:call identifier l_par arg_list? r_par [ce1]:cmd_end {-> New statement.call (identifier, [arg_list.arg]) } | {if} [cs1]:cmd_start [i1]:if expr cmd_end statement* [cs2]:cmd_start end [i2]:if? [ce2]:cmd_end {-> New statement.if (expr, [statement], []) } | {if_else} [cs1]:cmd_start [i1]:if expr cmd_end statement* [cs3]:cmd_start else [ce3]:cmd_end [estmt]:statement* [cs2]:cmd_start end [i2]:if? [ce2]:cmd_end {-> New statement.if (expr, [statement], [estmt.statement]) } | {separator} cmd_start sep expr cmd_end {-> New statement.separator(expr) } | {print} cmd_start print expr cmd_end {-> New statement.print(expr) } ; foreach_arg {-> identifier}= identifier in {-> identifier} ; arg {-> arg} = identifier equals expr {-> New arg(identifier, expr) } ; arg_list {-> arg*} = {simple} arg {-> [arg.arg] } | {list} arg_list comma arg {-> [arg_list.arg arg.arg] } ; oarg {-> oarg} = identifier oarg_tail? {-> New oarg(identifier, oarg_tail.expr) } ; oarg_tail {-> expr} = equals expr {-> expr} ; oarg_list {-> oarg*} = {simple} oarg {-> [oarg.oarg] } | {list} oarg_list comma oarg {-> [oarg_list.oarg oarg.oarg] } ; choose_when {-> choose_when } = [d1]:data? [cs1]:cmd_start [c1]:when expr [ce1]:cmd_end statement* [cs2]:cmd_start end [c2]:when? [ce2]:cmd_end {-> New choose_when (expr, [statement]) } ; choose_otherwise {-> [otherwise]:statement* } = [d1]:data? [cs1]:cmd_start [o1]:otherwise [ce1]:cmd_end statement* [cs2]:cmd_start end [o2]:otherwise? [ce2]:cmd_end {-> [statement] } ; expr {-> expr} = {concat} [e1]:expr plus [e2]:expr2 {-> New expr.concat(e1.expr, e2.expr) } | {other} [e1]:expr2 {-> e1.expr} ; expr2 {-> expr} = {literal} literal {-> New expr.literal(literal) } | {xpath} xpath {-> New expr.xpath(xpath) } | {iattrib} iattrib {-> New expr.iattrib(iattrib) } | {ivar} ivar {-> New expr.ivar(ivar) } | {group} l_par expr r_par {-> expr.expr } ; Abstract Syntax Tree script = statement*; statement = {data} data | {foreach} [var]:identifier? [xpath]:xpath statement* | {reverse_foreach} [var]:identifier? [xpath]:xpath statement* | {include} [path]:literal | {ecmascript} [script]:data | {if} [test]:expr statement* [else]:statement* | {choose} choose_when* [otherwise]:statement* | {set} [args]:arg+ | {param} [args]:oarg+ | {output} [expr]:expr statement* | {template} [name]:identifier [args]:oarg* statement* | {call} [name]:identifier [args]:arg* | {print} expr | {separator} expr ; choose_when = [test]:expr statement* ; oarg = [var]:identifier [expr]:expr? ; arg = [var]:identifier [expr]:expr ; expr = {literal} literal | {xpath} xpath | {ixpath} ixpath | {iattrib} iattrib | {ivar} ivar | {concat} [e1]:expr [e2]:expr ;