Source

PyvaScript / pyvascript / translator.ometa

grammar = stmt*:s -> '%s\n' % '\n'.join(s)

block = ~~[anything*] !(self.indent()):i [stmt*:s] !(self.dedent()) -> self.make_block(s, i)
funcblock = ~~[anything*] !(self.indent()):i [stmt*:s] !(self.dedent()) -> self.make_func_block(s, i)
stmt = (  ['while' while:e]
        | ['if' if:e]
        | ['for' for:e]
        | ['try' try:e]
        | ['func' funcstmt:e]) -> '%s\n' % e
     | ['global' [expr*:names]] !(self.register_globals(names)) -> ''
     | ['pass'] -> ''
     | ['call' ~~(['name' 'JS'] anything*) call:e] -> e
     | expr:e            -> '%s;' % e
expr = [:t apply(t):ans] -> ans

augassign :op expr:l expr:r !(self.register_var(l)) -> '%s %s %s' % (l, op, r)
assign expr:l expr:r !(self.register_var(l)) -> '%s = %s' % (l, r)

get     expr:x            -> x
getattr expr:x expr:y     -> '%s.%s' % (x, y)
getitem expr:x ( ['slice' (expr | anything):start
                  (expr | anything):end]                  -> '%s.slice(%s)' % (x, (start if start is not None else '0') + (', ' + end if end is not None else ''))
               | ['unop' '-'
                  [('number' | 'hexnumber') :i ?(i > 0)]] -> '%s.slice(%s)[0]' % (x, -i if i == 1 else '%s, %s' % (-i, -i+1))
               | expr:y                                   -> '%s[%s]' % (x, y)
               )
del     expr:x            -> 'delete %s' % x

unop     'not' ['call' ['name' 'hasattr'] [expr:obj expr:attr]] -> '(typeof %s[%s] == "undefined")' % (obj, attr)
unop     :op expr:x        -> '(%s%s)' % (self.op_map.get(op, op), x)

binop    'not in' expr:x expr:y -> '!(%s in %s)' % (x, y)
binop    :op expr:x expr:y -> '(%s %s %s)' % (x, self.binop_map.get(op, op), y)

name      :n       -> self.get_name(n)
number    :n       -> str(n)
hexnumber :n       -> hex(n)
string    :s       -> json.dumps(s)

new  expr:c                  -> 'new %s' % c

call ['name' 'len'] [expr:obj] -> '%s.length' % obj
call ['name' 'hasattr'] [expr:obj expr:attr] -> '(typeof %s[%s] != "undefined")' % (obj, attr)
call ['name' 'getattr'] [expr:obj expr:attr] -> '%s[%s]' % (obj, attr)
call ['name' 'setattr'] [expr:obj expr:attr expr:value] -> '%s[%s] = %s' % (obj, attr, value)
call ['name' 'JS'] ([['string' :js]] -> '%s' % js
                   |[expr:js]        -> 'eval(%s)' % js
                   )
call expr:fn [expr*:args]            -> '%s(%s)' % (fn, ', '.join(args))

list  !(self.indent()) expr*:xs !(self.dedent()) -> '[%s]' % ', '.join(xs)
tuple !(self.indent()) expr*:xs !(self.dedent()) -> '[%s]' % ', '.join(xs)
set   !(self.indent()) expr*:xs !(self.dedent()) -> 'set([%s])' % ', '.join(xs)
dict  !(self.indent()):i expr*:xs !(self.dedent()) -> self.make_dict(xs, i)

dictkv expr:k expr:v -> '%s: %s' % (k, v)

self            -> 'this'
break           -> 'break'
continue        -> 'continue'
return   expr:x -> 'return %s' % x
return          -> 'return'
raise    expr:x -> 'throw %s' % x

while expr:cond block:body -> 'while (%s) %s' % (cond, ''.join(body))

if [expr:cond block:t] [([expr:c block:b] -> (c, b))*:ei] block?:e -> self.make_if(cond, t, ei, e)
ifexpr expr:cond expr:t expr:f -> '(%s ? %s : %s)' % (cond, t, f)

isliteral = ~~[('name' | 'number' | 'hexnumber' | 'string') anything*] -> True
          | -> False

for expr:var !(self.register_var(var))
    ( ['call' ['name' 'range'] [(isliteral:lit expr:e -> (lit, e))+:r ?(len(r) <= 3)]] block:body -> self.make_for_range(var, r, body)
    | ['call' ['name' 'reversed'] [['call' ['name' 'range'] [(isliteral:lit expr:e -> (lit, e))+:r ?(len(r) <= 3)]]]] block:body -> self.make_for_reversed_range(var, r, body)
    | expr:data block:body -> self.make_for(var, data, body)
    )

defaultarg expr:name expr:default -> (name, default)
stararg :name -> (name,)
func funcstmt:f -> '(%s)' % f
funcstmt !(self.push_vars()) :name [[expr*:args] :stararg] !(self.register_globals(args)) funcblock:body !(self.pop_vars()) -> self.make_func(name, args, stararg, body)

try block:body expr:err block:errbody block?:finbody -> 'try %s catch(%s) %s' % (body, err, errbody) + (' finally %s' % finbody if finbody else '')