include 'peg/sexp'
node = object.new
node.prototype [
init: { name |
my.node_name = name
export my, name
}
to_s: { "<#{my.node_name}: #{my.matched}>" }
]
each_ast = { elements, block |
elements.each { e |
when { e.has_method?(:ast)} { block e.ast }
{ e.has_method?(:elements) } { each_ast e.elements, ->block }
}
}
add_ast = { node, list |
each_ast node.elements, { n |
true? n
{ list << n }
}
list
}
ast = { name, block |
n = node.new name
n.ast = ->block
}
ast :grammar {
add_ast my, s[:grammar]
}
ast :rule_def {
name = my.elements.deq.text
add_ast my, s[:rule_def, name]
}
ast :rule_list {
list = s[:any]
add_ast my, list
true? list.nodes.length == 1
{ list.nodes.first }
{ list }
}
ast :rule_seq {
list = s[:seq]
add_ast my, list
true? list.nodes.length == 1
{ list.nodes.first }
{ list }
}
ast :str_lit {
s[:str, my.content.text]
}
ast :rule_ref {
s[:rule_ref my.name.text]
}
ast :regex_rule {
s[:regex, my.content.text]
}
ast :rule_label {
add_ast my, s[:label, my.label_name.text]
}
ast :maybe_rule {
add_ast my, s[:maybe]
}
ast :many_rule {
add_ast my, s[:many]
}
ast :kleene_rule {
add_ast my, s[:kleene]
}
ast :not_rule {
add_ast my, s[:no]
}
ast :and_rule {
add_ast my, s[:and]
}
ast :anything_rule {
s[:anything]
}
ast :set_action {
s[:action, my.text]
}
ast :set_squish {
s[:squish, my.elements.first.matches[1]]
}