Class: Dhaka::Parser
- Inherits:
-
Object
- Object
- Dhaka::Parser
- Includes:
- ParserMethods
- Defined in:
- lib/dhaka/parser/parser.rb
Overview
The parser generator. To generate a parser from a grammar specification ArithmeticPrecedenceGrammar
, one would write:
parser = Dhaka::Parser.new(ArithmeticPrecedenceGrammar)
To compile this parser to Ruby source as ArithmeticPrecedenceParser
:
parser.compile_to_ruby_source_as(:ArithmeticPrecedenceParser)
which returns a string of Ruby code.
Instance Attribute Summary collapse
-
#grammar ⇒ Object
readonly
Returns the value of attribute grammar.
Instance Method Summary collapse
-
#compile_to_ruby_source_as(parser_class_name) ⇒ Object
Returns the Ruby source of the generated parser compiled as
parser_class_name
. -
#initialize(grammar, logger = nil) ⇒ Parser
constructor
Creates a new parser from the given grammar.
- #inspect ⇒ Object
-
#to_dot(options = {}) ⇒ Object
Returns the dot representation of the parser.
Methods included from ParserMethods
Constructor Details
#initialize(grammar, logger = nil) ⇒ Parser
Creates a new parser from the given grammar. Messages are logged by default to STDOUT and the log level is WARN. Shift-reduce conflicts are reported at WARN and reduce-reduce conflicts at ERROR. You may pass in your own logger. Logging at DEBUG shows a lot of progress output.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/dhaka/parser/parser.rb', line 16 def initialize(grammar, logger = nil) @shift_actions = Hash.new {|hash, state| hash[state] = ShiftAction.new(state)} @reduce_actions = Hash.new {|hash, production| hash[production] = ReduceAction.new(production)} @logger = logger || default_logger @transitions = Hash.new {|hash, state| hash[state] = {}} @grammar = grammar @channels = Hash.new {|hash, start_item| hash[start_item] = []} @states = Hash.new do |hash, kernel| closure, channels = grammar.closure(kernel) channels.each do |start_item, channel_set| @channels[start_item].concat channel_set.to_a end new_state = ParserState.new(self, closure) hash[kernel] = new_state @logger.debug("Created #{new_state.unique_name}.") new_state.transition_items.each do |symbol, items| destination_kernel = ItemSet.new(items.collect{|item| item.next_item}) destination_state = hash[destination_kernel] items.each {|item| @channels[item] << grammar.passive_channel(item, destination_state.items[item.next_item])} @transitions[new_state][symbol] = destination_state end new_state end initialize_states end |
Instance Attribute Details
#grammar ⇒ Object (readonly)
Returns the value of attribute grammar.
11 12 13 |
# File 'lib/dhaka/parser/parser.rb', line 11 def grammar @grammar end |
Instance Method Details
#compile_to_ruby_source_as(parser_class_name) ⇒ Object
Returns the Ruby source of the generated parser compiled as parser_class_name
. This can be written out to a file.
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/dhaka/parser/parser.rb', line 43 def compile_to_ruby_source_as parser_class_name result = "class #{parser_class_name} < Dhaka::CompiledParser\n\n" result << " self.grammar = #{grammar.name}\n\n" result << " start_with #{start_state.id}\n\n" states.each do |state| result << "#{state.compile_to_ruby_source}\n\n" end result << "end" result end |
#inspect ⇒ Object
68 69 70 |
# File 'lib/dhaka/parser/parser.rb', line 68 def inspect "<Dhaka::Parser grammar : #{grammar}>" end |
#to_dot(options = {}) ⇒ Object
Returns the dot representation of the parser. If :hide_lookaheads
is set to true in the options hash, lookaheads are not written out to the parser states, which is helpful when there are dozens of lookahead symbols for every item in every state.
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/dhaka/parser/parser.rb', line 57 def to_dot( = {}) Dot::Digraph.new(:fontsize => 10, :shape => :box, :size => 5) do |g| states.each do |state| g.node(state, :label => state.items.values.collect{|item| item.to_s()}.join("\n")) @transitions[state].each do |symbol, dest_state| g.edge(state, dest_state, :label => symbol.name) end end end.to_dot end |