_(&block)
click to toggle source
_add(target, x)
click to toggle source
def _add(target, x)
case x
when Sym
@delayed.each do |rule|
rule.replace x, target if rule.target == x
end
@grammar.symboltable.delete x
else
x.each_rule do |r|
r.target = target
@grammar.add r
end
end
flush_delayed
end
_added?(sym)
click to toggle source
def _added?(sym)
@grammar.added?(sym) or @delayed.detect {|r| r.target == sym }
end
_delayed_add(rule)
click to toggle source
def _delayed_add(rule)
@delayed.push rule
end
_intern(x)
click to toggle source
def _intern(x)
case x
when Symbol, String
@grammar.intern(x)
when Racc::Sym
x
else
raise TypeError, "wrong type #{x.class} (expected Symbol/String/Racc::Sym)"
end
end
action(&block)
click to toggle source
def action(&block)
id = "@#{@seqs["action"] += 1}".intern
_delayed_add Rule.new(@grammar.intern(id), [], UserAction.proc(block))
id
end
flush_delayed()
click to toggle source
def flush_delayed
return if @delayed.empty?
@delayed.each do |rule|
@grammar.add rule
end
@delayed.clear
end
grammar()
click to toggle source
def grammar
flush_delayed
@grammar.each do |rule|
if rule.specified_prec
rule.specified_prec = @grammar.intern(rule.specified_prec)
end
end
@grammar.init
@grammar
end
many(sym, &block)
click to toggle source
def many(sym, &block)
_defmetasyntax("many", _intern(sym), block) {|target|
seq() { [] }\
| seq(target, sym) {|list, x| list.push x; list }
}
end
many1(sym, &block)
click to toggle source
def many1(sym, &block)
_defmetasyntax("many1", _intern(sym), block) {|target|
seq(sym) {|x| [x] }\
| seq(target, sym) {|list, x| list.push x; list }
}
end
method_missing(mid, *args, &block)
click to toggle source
def method_missing(mid, *args, &block)
unless mid.to_s[-1,1] == '='
super
end
target = @grammar.intern(mid.to_s.chop.intern)
unless args.size == 1
raise ArgumentError, "too many arguments for #{mid} (#{args.size} for 1)"
end
_add target, args.first
end
null(&block)
click to toggle source
def null(&block)
seq(&block)
end
option(sym, default = nil, &block)
click to toggle source
def option(sym, default = nil, &block)
_defmetasyntax("option", _intern(sym), block) {|target|
seq() { default } | seq(sym)
}
end
precedence_table(&block)
click to toggle source
def precedence_table(&block)
env = PrecedenceDefinitionEnv.new(@grammar)
env.instance_eval(&block)
@grammar.end_precedence_declaration env.reverse
end
separated_by(sep, sym, &block)
click to toggle source
def separated_by(sep, sym, &block)
option(separated_by1(sep, sym), [], &block)
end
separated_by1(sep, sym, &block)
click to toggle source
def separated_by1(sep, sym, &block)
_defmetasyntax("separated_by1", _intern(sym), block) {|target|
seq(sym) {|x| [x] }\
| seq(target, sep, sym) {|list, _, x| list.push x; list }
}
end
seq(*list, &block)
click to toggle source
def seq(*list, &block)
Rule.new(nil, list.map {|x| _intern(x) }, UserAction.proc(block))
end
_register(target_name)
click to toggle source
def _register(target_name)
target = target_name.intern
unless _added?(@grammar.intern(target))
yield(target).each_rule do |rule|
rule.target = @grammar.intern(target)
_delayed_add rule
end
end
target
end
_wrap(target_name, sym, block)
click to toggle source
def _wrap(target_name, sym, block)
target = target_name.intern
_delayed_add Rule.new(@grammar.intern(target),
[@grammar.intern(sym.intern)],
UserAction.proc(block))
target
end