diff --git a/assets/parser.c.erb b/assets/parser.c.erb index 45002b8..cae1f92 100644 --- a/assets/parser.c.erb +++ b/assets/parser.c.erb @@ -974,7 +974,7 @@ size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * context) { /* Successful parse. */ <% if @grammar.ast %> - context->parse_result = (<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> *)state_values_stack_index(&statevalues, -1)->ast_node; + context->parse_result = state_values_stack_index(&statevalues, -1)->ast_node; <% else %> context->parse_result = state_values_stack_index(&statevalues, -1)->pvalue; <% end %> @@ -1110,13 +1110,13 @@ size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * context) * @return Parse result value. */ <% if @grammar.ast %> -<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) +<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) <% else %> <%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) <% end %> { <% if @grammar.ast %> - return context->parse_result; + return (<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> *) context->parse_result; <% else %> return context->parse_result.v_<%= start_rule_type[0] %>; <% end %> @@ -1184,7 +1184,7 @@ static void free_ast_node(ASTNode * node) /** * Free all AST node memory. */ -void <%= @grammar.prefix %>free_ast(<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * ast) +void <%= @grammar.prefix %>free_ast(<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> * ast) { free_ast_node((ASTNode *)ast); } diff --git a/assets/parser.d.erb b/assets/parser.d.erb index a643652..b3d1a0f 100644 --- a/assets/parser.d.erb +++ b/assets/parser.d.erb @@ -173,7 +173,7 @@ public struct <%= @grammar.prefix %>context_t /** Parse result value. */ <% if @grammar.ast %> - <%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * parse_result; + void * parse_result; <% else %> <%= @grammar.prefix %>value_t parse_result; <% end %> @@ -1031,7 +1031,7 @@ public size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * cont { /* Successful parse. */ <% if @grammar.ast %> - context.parse_result = cast(<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> *)statevalues[$-1].ast_node; + context.parse_result = statevalues[$-1].ast_node; <% else %> context.parse_result = statevalues[$-1].pvalue; <% end %> @@ -1156,13 +1156,13 @@ public size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * cont * @return Parse result value. */ <% if @grammar.ast %> -public <%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) +public <%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) <% else %> public <%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context) <% end %> { <% if @grammar.ast %> - return context.parse_result; + return cast(<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> *)context.parse_result; <% else %> return context.parse_result.v_<%= start_rule_type[0] %>; <% end %> diff --git a/assets/parser.h.erb b/assets/parser.h.erb index 86a8b1e..b88841d 100644 --- a/assets/parser.h.erb +++ b/assets/parser.h.erb @@ -162,7 +162,7 @@ typedef struct /** Parse result value. */ <% if @grammar.ast %> - <%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * parse_result; + void * parse_result; <% else %> <%= @grammar.prefix %>value_t parse_result; <% end %> @@ -191,9 +191,9 @@ size_t <%= @grammar.prefix %>lex(<%= @grammar.prefix %>context_t * context, <%= size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * context); <% if @grammar.ast %> -<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); +<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); -void <%= @grammar.prefix %>free_ast(<%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * ast); +void <%= @grammar.prefix %>free_ast(<%= @grammar.ast_prefix %><%= @grammar.start_rules[0] %><%= @grammar.ast_suffix %> * ast); <% else %> <%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); <% end %> diff --git a/lib/propane/generator.rb b/lib/propane/generator.rb index e54e8dd..9c47a90 100644 --- a/lib/propane/generator.rb +++ b/lib/propane/generator.rb @@ -71,12 +71,14 @@ class Propane end tokens_by_name[token.name] = token end - # Check for user start rule. - unless @grammar.rules.find {|rule| rule.name == @grammar.start_rule} - raise Error.new("Start rule `#{@grammar.start_rule}` not found") + # Check for user start rules. + @grammar.start_rules.each_with_index do |start_rule, i| + unless @grammar.rules.find {|rule| rule.name == start_rule} + raise Error.new("Start rule `#{start_rule}` not found") + end + # Add "real" start rule. + @grammar.rules.unshift(Rule.new("$#{start_rule}", [start_rule, "$EOF"], nil, nil, nil)) end - # Add "real" start rule. - @grammar.rules.unshift(Rule.new("$Start", [@grammar.start_rule, "$EOF"], nil, nil, nil)) # Generate and add rules for optional components. generate_optional_component_rules!(tokens_by_name) # Build rule sets. @@ -332,9 +334,9 @@ class Propane # # @return [Array] # Start rule parser value type name and type string. - def start_rule_type + def start_rule_type(start_rule_index = 0) start_rule = @grammar.rules.find do |rule| - rule.name == @grammar.start_rule + rule.name == @grammar.start_rules[start_rule_index] end [start_rule.ptypename, @grammar.ptypes[start_rule.ptypename]] end diff --git a/lib/propane/grammar.rb b/lib/propane/grammar.rb index f12c330..cef26eb 100644 --- a/lib/propane/grammar.rb +++ b/lib/propane/grammar.rb @@ -12,7 +12,7 @@ class Propane attr_reader :modulename attr_reader :patterns attr_reader :rules - attr_reader :start_rule + attr_reader :start_rules attr_reader :tokens attr_reader :code_blocks attr_reader :ptypes @@ -20,7 +20,7 @@ class Propane def initialize(input) @patterns = [] - @start_rule = "Start" + @start_rules = [] @tokens = [] @rules = [] @code_blocks = {} @@ -35,6 +35,7 @@ class Propane @ast_suffix = "" @free_token_node = nil parse_grammar! + @start_rules << "Start" if @start_rules.empty? end def ptype @@ -242,7 +243,7 @@ class Propane def parse_start_statement! if md = consume!(/start\s+(\w+)\s*;/) - @start_rule = md[1] + @start_rules << md[1] unless @start_rules.include?(md[1]) end end