class Hammer::ParserBuilder
Attributes
parsers[R]
Public Class Methods
new()
click to toggle source
# File lib/hammer/parser_builder.rb, line 21 def initialize @parsers = [] end
Private Class Methods
define_parser(name, options = {})
click to toggle source
Defines a parser constructor with the given name.
# File lib/hammer/parser_builder.rb, line 64 def self.define_parser(name, options = {}) define_method name do |*args| # TODO: This is wrong!! Needs to accept a block for nested parsers! @parsers << Hammer::Parser.send(name, *args) return self end end
Public Instance Methods
action(&block)
click to toggle source
modifies previous parser
# File lib/hammer/parser_builder.rb, line 56 def action(&block) parser = @parsers.last raise RuntimeError, 'need a parser before action' if parser.nil? @parsers << Hammer::Parser.action(parser, &block) return self end
build()
click to toggle source
# File lib/hammer/parser_builder.rb, line 25 def build if @parsers.length > 1 Hammer::Parser.sequence(*@parsers) else @parsers.first end end
call(parser)
click to toggle source
# File lib/hammer/parser_builder.rb, line 50 def call(parser) @parsers << parser return self end
choice(*parsers, &block)
click to toggle source
# File lib/hammer/parser_builder.rb, line 42 def choice(*parsers, &block) if block_given? parsers += Docile.dsl_eval(ParserBuilder.new, &block).parsers end @parsers << Hammer::Parser.choice(*parsers) return self end
indirect()
click to toggle source
At least indirect must return the parser instead of the builder, so it can be stored in a variable. Other possible solution:
Make indirect take a name parameter, and use the name to bind it later. Example: p = Hammer::Parser.build { indirect(:the_name) } p.bind(:the_name, inner_parser) (store names and parsers in hash in the builder, when building merge hashes from sub builders and store everything in the resulting sequence or choice. make Parser#bind take and optional symbol. if it is given, the name is looked up in the table.)
TODO:
Think about this more. Do we need to be able to build parsers by chaining function calls? DSL should be sufficient. If yes, the parser methods in this class should not return "self", but the Hammer::Parser object they create.
# File lib/hammer/parser_builder.rb, line 116 def indirect parser = Hammer::Parser.indirect @parsers << parser return parser end
sequence(*parsers, &block)
click to toggle source
can call it either as ParserBuiler.new.sequence(parser1, parser2, parser3) or as Parser.build
{ sequence { call parser1; call parser2; call parser3 } }
# File lib/hammer/parser_builder.rb, line 36 def sequence(*parsers, &block) @parsers += parsers @parsers << Docile.dsl_eval(ParserBuilder.new, &block).build if block_given? return self end