Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

224 lines (168 sloc) 5.538 kb
use("core")
use("define")
use("control-flow")
use("dynamic")
use("particles")
use("comparison")
use("node")
require("kpeg")
require("set")
Actions = dynamic
Setups = dynamic
Vars = dynamic
Rule = dynamic
RuleVars = dynamic
const-name(c: Atomy::AST::Constant) := c name to-s
const-name(c: Atomy::AST::ScopedConstant) := const-name(c parent) + "::" + c name to-s
const-name(c: Atomy::AST::ToplevelConstant) := "::" + c name to-s
process-val(g, `(%((~grammar).) ~(x)(~*args))) := do:
`(~g foreign-invoke(
~(grammar text)
~(x text)
~(args collect .show join(", "))))
process-val(g, `(~a %((~grammar).) ~(x)(~*args))) := do:
`(~g seq(
~process-val(g, a),
~g foreign-invoke(
~(grammar text)
~(x text)
~(args collect .show join(", ")))))
process-val(g, `(%((~grammar).) ~x)) := do:
`(~g foreign-invoke(~(grammar text), ~(x text)))
process-val(g, `(~a %((~grammar).) ~x)) := do:
`(~g seq(~process-val(g, a), ~g foreign-invoke(~(grammar text), ~(x text))))
process-val(g, `((~v)= ~name)) := do:
val = process-val(g, v)
when(^RuleVars): ^RuleVars << name text
`(~g t(~val, ~(name text to-s)))
process-val(g, `(~a (~v)= ~name)) := do:
val = process-val(g, v)
when(^RuleVars): ^RuleVars << name text
`(~g seq(~process-val(g, a), ~g t(~val, ~(name text to-s))))
process-val(g, `(~a ~b)) :=
`(~g seq(~process-val(g, a), ~process-val(g, b)))
process-val(g, `(~a | ~b)) :=
process-val(g, `[~a, ~b])
process-val(g, `[~*xs]) := do:
vars = ^RuleVars dup
choices =
xs collect [x]:
let(RuleVars = vars dup):
process-val(g, x)
`(~g any(~*choices))
process-val(g, a: `{ ~*bs }) :=
if(^Actions)
then:
vars = ^RuleVars to-a
call = "actions[" + ^Actions size to-s + "][" + vars collect .to-s join(", ") + "]"
^Actions << [a, vars]
`(~g action(~call))
else:
`(~g action({ ~*bs }))
process-val(g, `(<(~x)>)) := do:
val = process-val(g, x)
when(^RuleVars): ^RuleVars << .text
`(~g collect(~val))
process-val(g, `(@<(~x)>)) :=
`(~g bounds(~process-val(g, x)))
process-val(g, s: Atomy::AST::String) :=
`(~g str(~s))
process-val(g, `(/(~(b: Atomy::AST::String))/)) :=
`(~g reg(~(b raw)))
process-val(g, c: Atomy::AST::Call) := do:
args = "(" + c arguments collect .show join(", ") + ")"
`(~g ref(~(c name text to-s), nil, ~args))
process-val(g, `@~(c: Atomy::AST::Call)) := do:
args = "(" + c arguments collect .show join(", ") + ")"
`(~g invoke(~(c name text to-s), ~args))
process-val(g, `^~(c: Atomy::AST::Call)) := do:
args = "(" + c arguments collect .show join(", ") + ")"
`(~g foreign-invoke("parent", ~(c name text to-s), ~args))
process-val(g, w: Atomy::AST::Word) :=
`(~g ref(~(w text to-s)))
process-val(g, `@~(w: Atomy::AST::Word)) := do:
`(~g invoke(~(w text to-s)))
process-val(g, `^~(w: Atomy::AST::Word)) := do:
`(~g foreign-invoke("parent", ~(w text to-s)))
process-val(g, `((~v)?)) :=
`(~g maybe(~process-val(g, v)))
process-val(g, `((~v)+)) :=
`(~g many(~process-val(g, v)))
process-val(g, `((~v)*)) :=
`(~g kleene(~process-val(g, v)))
process-val(g, `&~v) :=
`(~g andp(~process-val(g, v)))
process-val(g, `!~v) :=
`(~g notp(~process-val(g, v)))
process-val(g, '_) :=
`(~g dot)
process-val(_, s) :=
raise(ArgumentError, "unknown operator: " + s to-sexp inspect)
Atomy::AST open:
ast(ParserDefiner(@source))
ParserDefiner bytecode(g) := do:
g push-rubinius
g push-literal(.__parser_init__)
g push-literal(Rubinius::Compiler compile-string(@source))
g push-scope
g push-self
g send(.attach-method, 4)
g pop
g push-self
g send(.__parser_init__, 0)
macro(grammar: ~*body): names [g]:
b = body collect [n]:
n match:
`%%{ ~*xs } -> do:
call =
if(^Setups)
then:
^Setups << `{ ~*xs }
"setups[" + (^Setups size - 1) to-s + "][]"
else:
`{ ~*xs }
`(~g add-setup(~g action(~call)))
`(%~name := ~const) ->
`(~g add-foreign-grammar(~(name text to-s), ~const-name(const)))
`(%~name = ~expr) -> do:
-- TODO: fix this, yo
call =
if(^Vars)
then:
^Vars << `{ ~*xs }
"vars[" + (^Vars size - 1) to-s + "][]"
else:
`{ ~*xs }
`(~g set-variable(~(name text to-s), call))
`(~(name)(~*args) := ~val) -> do:
let(Rule = name text,
RuleVars = ::Set new(args collect .text)):
`(~g set(~(name text to-s)
~process-val(g, val)
~(args collect [x]: x text to-s)))
`(~name := ~val) -> do:
let(Rule = name text,
RuleVars = ::Set new):
`(~g set(~(name text to-s), ~process-val(g, val)))
_ -> `unknown(~n)
`(::KPeg::Grammar new tap [~g]: ~*b)
macro(parser(~name): ~*grammar):
let(Actions = Array[],
Setups = Array[],
Vars = Array[]):
g = `(grammar: ~*grammar) evaluate
acts =
^Actions collect [action, as]:
args = as collect [a]: Atomy::AST::Word new(0, a)
`([~*args] ~action)
def =
Atomy::AST::ParserDefiner new(
node line
::KPeg::CodeGenerator new(const-name(name), g) output)
`(do:
~name = ::KPeg::CompiledParser class:
{ self } setups := @setups ||= ~^Setups
{ self } vars := @vars ||= ~^Vars
actions := @actions ||= ~acts
~def
~name)
Jump to Line
Something went wrong with that request. Please try again.