diff --git a/Steepfile b/Steepfile index 64438489..e8bffb98 100644 --- a/Steepfile +++ b/Steepfile @@ -12,6 +12,7 @@ target :lib do check "lib/lrama/grammar/parameterizing_rule_resolver.rb" check "lib/lrama/grammar/parameterizing_rule_rhs_builder.rb" check "lib/lrama/grammar/parameterizing_rules" + check "lib/lrama/grammar/parser_state.rb" check "lib/lrama/grammar/percent_code.rb" check "lib/lrama/grammar/precedence.rb" check "lib/lrama/grammar/printer.rb" diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index 6759c176..ff09cf78 100644 --- a/lib/lrama/grammar.rb +++ b/lib/lrama/grammar.rb @@ -2,6 +2,7 @@ require "lrama/grammar/code" require "lrama/grammar/counter" require "lrama/grammar/error_token" +require "lrama/grammar/parser_state" require "lrama/grammar/percent_code" require "lrama/grammar/precedence" require "lrama/grammar/printer" @@ -20,7 +21,7 @@ module Lrama # Grammar is the result of parsing an input grammar file class Grammar - attr_reader :percent_codes, :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux + attr_reader :percent_codes, :parser_states, :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux attr_accessor :union, :expect, :printers, :error_tokens, :lex_param, :parse_param, :initial_action, @@ -35,6 +36,7 @@ def initialize(rule_counter) @percent_codes = [] @printers = [] @error_tokens = [] + @parser_states = [] @symbols = [] @types = [] @rule_builders = [] @@ -63,6 +65,10 @@ def add_error_token(ident_or_tags:, token_code:, lineno:) @error_tokens << ErrorToken.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno) end + def add_parser_state(state_id, state_list) + @parser_states << ParserState.new(state_id: state_id, state_list: state_list) + end + def add_term(id:, alias_name: nil, tag: nil, token_id: nil, replace: false) if token_id && (sym = @symbols.find {|s| s.token_id == token_id }) if replace @@ -195,7 +201,7 @@ def find_symbol_by_id(id) end def find_symbol_by_id!(id) - find_symbol_by_id(id) || (raise "Symbol not found: #{id}") + find_symbol_by_id(id) || (raise "Symbol not found: #{id.s_value}") end def find_symbol_by_number!(number) diff --git a/lib/lrama/grammar/parser_state.rb b/lib/lrama/grammar/parser_state.rb new file mode 100644 index 00000000..b9de26bd --- /dev/null +++ b/lib/lrama/grammar/parser_state.rb @@ -0,0 +1,144 @@ +module Lrama + class Grammar + class ParserState + attr_reader :state_id, :state_list + + def initialize(state_id:, state_list:) + @state_id = state_id + @state_list = state_list + end + + def enum_definition + <<~ENUM + enum #{enum_name} + { + #{enum_body} + }; + typedef enum #{enum_name} #{enum_type}; + + static const char *const #{enum_name_table_name}[] = { + #{int_to_name.join(", ")} + }; + + YY_ATTRIBUTE_UNUSED + static const char * + #{enum_name}_name (#{enum_type} num) + { + return #{enum_name_table_name}[num]; + } + + # define #{state_name_macro}(value) #{enum_name}_name (value) + # define #{current_state_name_macro} #{state_name_macro} (*#{stack_prefix}_p) + ENUM + end + + def state_name_macro + "YY_STATE_#{state_name.upcase}_NAME" + end + + def current_state_name_macro + "YY_CURRENT_STATE_#{state_name.upcase}_NAME" + end + + def states_functions + <<~FUNC + # define YYPUSH_STATE_#{state_name.upcase}(value) \\ + do \\ + { \\ + if (#{stack_prefix}_b + #{states_stack_size_name} - 1 <= #{stack_prefix}_p) \\ + YYSTATE_STACK_INCREASE (#{stack_prefix}_a, #{stack_prefix}_b, #{stack_prefix}_p, #{states_stack_size_name}, "#{state_name}"); \\ + YYDPRINTF ((stderr, "Push %s to #{state_name}\\n", #{state_name_macro} (yyparser_state_ ## value))); \\ + *++#{stack_prefix}_p = yyparser_state_ ## value; \\ + } \\ + while (0) + + # define YYPOP_STATE_#{state_name.upcase}() \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Pop #{state_name}\\n")); \\ + if (#{stack_prefix}_p != #{stack_prefix}_b) \\ + { \\ + #{stack_prefix}_p -= 1; \\ + } \\ + else \\ + { \\ + YYDPRINTF ((stderr, "Try to pop empty #{state_name} stack\\n")); \\ + } \\ + } \\ + while (0) + + # define YYSET_STATE_#{state_name.upcase}(value) \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Set %s to #{state_name}\\n", #{state_name_macro} (yyparser_state_ ## value))); \\ + *#{stack_prefix}_p = yyparser_state_ ## value; \\ + } \\ + while (0) + + # define YY_STATE_#{state_name.upcase} #{stack_prefix}_p + FUNC + end + + def states_clean_up_stack + <<~CODE + if (#{stack_prefix}_b != #{stack_prefix}_a) + YYSTACK_FREE (#{stack_prefix}_b); + CODE + end + + def states_stack_size_name + "#{stack_prefix}_stacksize" + end + + def states_stacks + <<~STACKS + /* Current size of state stack size */ + YYPTRDIFF_T #{states_stack_size_name} = YYINITDEPTH; + + /* The parser state stack (#{stack_prefix}): array, bottom, top. */ + int #{stack_prefix}_a[YYINITDEPTH]; + int *#{stack_prefix}_b = #{stack_prefix}_a; + int *#{stack_prefix}_p = #{stack_prefix}_b; + STACKS + end + + def state_name + state_id.s_value + end + + def enum_name + "yyparser_state_#{state_name}" + end + + def enum_type + "#{enum_name}_t" + end + + def enum_body + enum_numbers.join(",\n ") + end + + def int_to_name + state_list.map do |state| + "\"#{state.s_value}\"" + end << "YY_NULLPTR" + end + + def enum_name_table_name + "#{enum_name}_names" + end + + def stack_prefix + "yyparser_state_#{state_name}" + end + + private + + def enum_numbers + state_list.map do |state| + "yyparser_state_#{state.s_value}" + end + end + end + end +end diff --git a/lib/lrama/grammar/reference.rb b/lib/lrama/grammar/reference.rb index 24c98129..d60edacb 100644 --- a/lib/lrama/grammar/reference.rb +++ b/lib/lrama/grammar/reference.rb @@ -2,11 +2,12 @@ module Lrama class Grammar # type: :dollar or :at # name: String (e.g. $$, $foo, $expr.right) - # index: Integer (e.g. $1) + # number: Integer (e.g. $1) + # index: # ex_tag: "$1" (Optional) - class Reference < Struct.new(:type, :name, :index, :ex_tag, :first_column, :last_column, keyword_init: true) + class Reference < Struct.new(:type, :name, :number, :index, :ex_tag, :first_column, :last_column, keyword_init: true) def value - name || index + name || number end end end diff --git a/lib/lrama/grammar/rule_builder.rb b/lib/lrama/grammar/rule_builder.rb index c0ec9d90..e255ddfa 100644 --- a/lib/lrama/grammar/rule_builder.rb +++ b/lib/lrama/grammar/rule_builder.rb @@ -120,6 +120,12 @@ def process_rhs(parameterizing_resolver) @parameterizing_rules = @parameterizing_rules + parameterizing.build @replaced_rhs << parameterizing.build_token end + when Lrama::Lexer::Token::ParserStatePop + process_parser_state_token(token, "parser_state_pop_", "YYPOP_STATE_#{token.s_value.upcase}();", i, parameterizing_resolver) + when Lrama::Lexer::Token::ParserStatePush + process_parser_state_token(token, "parser_state_push_", "YYPUSH_STATE_#{token.s_value.upcase}(#{token.state.s_value});", i, parameterizing_resolver) + when Lrama::Lexer::Token::ParserStateSet + process_parser_state_token(token, "parser_state_set_", "YYSET_STATE_#{token.s_value.upcase}(#{token.state.s_value});", i, parameterizing_resolver) when Lrama::Lexer::Token::UserCode prefix = token.referred ? "@" : "$@" new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s) @@ -138,29 +144,53 @@ def process_rhs(parameterizing_resolver) end end + def process_parser_state_token(token, prefix, code, position_in_original_rule_rhs, parameterizing_resolver) + new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + token.s_value + @midrule_action_counter.increment.to_s) + user_code = Lrama::Lexer::Token::UserCode.new(s_value: code, location: token.location) + + @replaced_rhs << new_token + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, position_in_original_rule_rhs, skip_preprocess_references: true) + rule_builder.lhs = new_token + rule_builder.user_code = user_code + rule_builder.complete_input + rule_builder.setup_rules(parameterizing_resolver) + + @rule_builders_for_derived_rules << rule_builder + end + def numberize_references # Bison n'th component is 1-origin (rhs + [user_code]).compact.each.with_index(1) do |token, i| next unless token.is_a?(Lrama::Lexer::Token::UserCode) token.references.each do |ref| + # Derive number reference index from named reference ref_name = ref.name if ref_name && ref_name != '$' if lhs.referred_by?(ref_name) ref.name = '$' else - candidates = rhs.each_with_index.select {|token, i| token.referred_by?(ref_name) } + candidates = referable_tokens.each_with_index.select {|token, i| token.referred_by?(ref_name) } raise "Referring symbol `#{ref_name}` is duplicated. #{token}" if candidates.size >= 2 raise "Referring symbol `#{ref_name}` is not found. #{token}" unless referring_symbol = candidates.first - ref.index = referring_symbol[1] + 1 + ref.number = referring_symbol[1] + 1 + end + end + + if ref.number + # Remapping number reference index to include non referable tokens + # TODO: Is it better to separate "number" of reference from actual "index" (Grammar::Reference)? + ref.index = number_to_index[ref.number] + + if !ref.index + raise "Can not refer to not exist component. $#{ref.number}" end end # TODO: Need to check index of @ too? next if ref.type == :at - if ref.index # TODO: Prohibit $0 even so Bison allows it? # See: https://www.gnu.org/software/bison/manual/html_node/Actions.html @@ -171,6 +201,39 @@ def numberize_references end end + def referable_token?(token) + case token + when Lrama::Lexer::Token::ParserStatePop + false + when Lrama::Lexer::Token::ParserStatePush + false + when Lrama::Lexer::Token::ParserStateSet + false + else + true + end + end + + def referable_tokens + rhs.select do |token| + referable_token?(token) + end + end + + def number_to_index + return @number_to_index if @number_to_index + + @number_to_index = [0] + + rhs.each.with_index(1) do |token, i| + if referable_token?(token) + @number_to_index << i + end + end + + @number_to_index + end + def flush_user_code if c = @user_code @rhs << c diff --git a/lib/lrama/lexer.rb b/lib/lrama/lexer.rb index 63a1a0a0..66392a01 100644 --- a/lib/lrama/lexer.rb +++ b/lib/lrama/lexer.rb @@ -29,6 +29,10 @@ class Lexer %empty %code %rule + %parser-state-push + %parser-state-pop + %parser-state-set + %parser-state ) def initialize(text) diff --git a/lib/lrama/lexer/token.rb b/lib/lrama/lexer/token.rb index 22b79837..2509c542 100644 --- a/lib/lrama/lexer/token.rb +++ b/lib/lrama/lexer/token.rb @@ -1,6 +1,9 @@ require 'lrama/lexer/token/char' require 'lrama/lexer/token/ident' require 'lrama/lexer/token/instantiate_rule' +require 'lrama/lexer/token/parser_state_pop' +require 'lrama/lexer/token/parser_state_push' +require 'lrama/lexer/token/parser_state_set' require 'lrama/lexer/token/tag' require 'lrama/lexer/token/user_code' diff --git a/lib/lrama/lexer/token/parser_state_pop.rb b/lib/lrama/lexer/token/parser_state_pop.rb new file mode 100644 index 00000000..ac2c020b --- /dev/null +++ b/lib/lrama/lexer/token/parser_state_pop.rb @@ -0,0 +1,8 @@ +module Lrama + class Lexer + class Token + class ParserStatePop < Token + end + end + end +end diff --git a/lib/lrama/lexer/token/parser_state_push.rb b/lib/lrama/lexer/token/parser_state_push.rb new file mode 100644 index 00000000..a665d884 --- /dev/null +++ b/lib/lrama/lexer/token/parser_state_push.rb @@ -0,0 +1,9 @@ +module Lrama + class Lexer + class Token + class ParserStatePush < Token + attr_accessor :state + end + end + end +end diff --git a/lib/lrama/lexer/token/parser_state_set.rb b/lib/lrama/lexer/token/parser_state_set.rb new file mode 100644 index 00000000..f31271b4 --- /dev/null +++ b/lib/lrama/lexer/token/parser_state_set.rb @@ -0,0 +1,9 @@ +module Lrama + class Lexer + class Token + class ParserStateSet < Token + attr_accessor :state + end + end + end +end diff --git a/lib/lrama/lexer/token/user_code.rb b/lib/lrama/lexer/token/user_code.rb index abe6fba2..5f06b9b7 100644 --- a/lib/lrama/lexer/token/user_code.rb +++ b/lib/lrama/lexer/token/user_code.rb @@ -38,7 +38,7 @@ def scan_reference(scanner) return Lrama::Grammar::Reference.new(type: :dollar, name: "$", ex_tag: tag, first_column: start, last_column: scanner.pos - 1) when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $1 tag = scanner[1] ? Lrama::Lexer::Token::Tag.new(s_value: scanner[1]) : nil - return Lrama::Grammar::Reference.new(type: :dollar, index: Integer(scanner[2]), ex_tag: tag, first_column: start, last_column: scanner.pos - 1) + return Lrama::Grammar::Reference.new(type: :dollar, number: Integer(scanner[2]), index: Integer(scanner[2]), ex_tag: tag, first_column: start, last_column: scanner.pos - 1) when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $program (named reference without brackets) tag = scanner[1] ? Lrama::Lexer::Token::Tag.new(s_value: scanner[1]) : nil return Lrama::Grammar::Reference.new(type: :dollar, name: scanner[2], ex_tag: tag, first_column: start, last_column: scanner.pos - 1) @@ -51,7 +51,7 @@ def scan_reference(scanner) when scanner.scan(/@\$/) # @$ return Lrama::Grammar::Reference.new(type: :at, name: "$", first_column: start, last_column: scanner.pos - 1) when scanner.scan(/@(\d+)/) # @1 - return Lrama::Grammar::Reference.new(type: :at, index: Integer(scanner[1]), first_column: start, last_column: scanner.pos - 1) + return Lrama::Grammar::Reference.new(type: :at, number: Integer(scanner[1]), index: Integer(scanner[1]), first_column: start, last_column: scanner.pos - 1) when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets) return Lrama::Grammar::Reference.new(type: :at, name: scanner[1], first_column: start, last_column: scanner.pos - 1) when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right (named reference with brackets) diff --git a/lib/lrama/output.rb b/lib/lrama/output.rb index f6720850..4fd82508 100644 --- a/lib/lrama/output.rb +++ b/lib/lrama/output.rb @@ -358,6 +358,34 @@ def percent_code(name) end.join end + def has_parser_states? + !@grammar.parser_states.empty? + end + + def parser_states_enums + @grammar.parser_states.map do |ps| + ps.enum_definition + end + end + + def parser_states_stacks + @grammar.parser_states.map do |ps| + ps.states_stacks + end + end + + def parser_states_functions + @grammar.parser_states.map do |ps| + ps.states_functions + end + end + + def parser_states_clean_up_stack + @grammar.parser_states.map do |ps| + ps.states_clean_up_stack + end + end + private def eval_template(file, path) diff --git a/lib/lrama/parser.rb b/lib/lrama/parser.rb index 6e45f97f..5ab817c5 100644 --- a/lib/lrama/parser.rb +++ b/lib/lrama/parser.rb @@ -658,7 +658,7 @@ def token_to_str(t) module Lrama class Parser < Racc::Parser -module_eval(<<'...end parser.y/module_eval...', 'parser.y', 500) +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 530) include Lrama::Report::Duration @@ -757,296 +757,318 @@ def carrets(text, first_column, last_column) ##### State transition tables begin ### racc_action_table = [ - 85, 44, 86, 145, 144, 67, 44, 44, 145, 187, - 67, 67, 44, 6, 187, 7, 67, 147, 196, 44, - 143, 43, 147, 188, 58, 163, 164, 165, 188, 3, - 44, 40, 43, 8, 67, 63, 34, 44, 148, 43, - 41, 87, 40, 148, 189, 47, 44, 80, 43, 189, - 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 47, 21, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 9, 44, 47, 43, 13, 14, 15, 16, 17, - 18, 50, 51, 19, 20, 21, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 44, 44, 43, 43, - 52, 70, 70, 44, 44, 43, 43, 53, 70, 70, - 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, - 67, 173, 44, 44, 43, 43, 67, 173, 44, 44, - 43, 43, 67, 173, 44, 44, 43, 43, 67, 173, - 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, - 67, 67, 44, 44, 43, 43, 67, 67, 44, 44, - 43, 43, 67, 67, 44, 44, 43, 43, 67, 67, - 44, 44, 43, 43, 67, 67, 163, 164, 165, 83, - 44, 44, 43, 43, 141, 190, 142, 191, 205, 54, - 191, 55, 76, 77, 81, 83, 88, 88, 88, 90, - 96, 100, 101, 104, 104, 104, 104, 107, 110, 111, - 113, 115, 116, 117, 118, 119, 122, 126, 127, 128, - 131, 132, 133, 135, 150, 152, 153, 154, 155, 156, - 157, 158, 131, 160, 168, 169, 178, 182, 183, 185, - 178, 83, 182, 201, 203, 83, 207, 83 ] + 87, 45, 88, 152, 142, 69, 3, 8, 45, 151, + 152, 45, 69, 44, 45, 69, 204, 154, 69, 45, + 35, 204, 143, 69, 154, 150, 45, 6, 44, 7, + 205, 60, 45, 42, 44, 205, 69, 65, 41, 155, + 156, 157, 158, 48, 48, 89, 155, 156, 157, 158, + 41, 45, 206, 44, 48, 82, 72, 206, 22, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 51, 52, + 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 9, 45, 53, 44, 13, 14, 15, 16, 17, 18, + 54, 55, 19, 20, 21, 22, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 216, 45, 45, 44, + 44, 56, 72, 72, 57, 78, 174, 175, 176, 45, + 45, 44, 44, 45, 72, 44, 79, 69, 187, 45, + 45, 44, 44, 69, 187, 45, 45, 44, 44, 69, + 187, 45, 45, 44, 44, 69, 187, 45, 45, 44, + 44, 69, 187, 45, 45, 44, 44, 69, 187, 45, + 45, 44, 44, 69, 69, 45, 45, 44, 44, 69, + 69, 45, 45, 44, 44, 69, 69, 45, 45, 44, + 44, 69, 69, 45, 45, 44, 44, 69, 174, 175, + 176, 85, 45, 45, 44, 44, 45, 148, 44, 149, + 207, 229, 208, 208, 83, 85, 90, 90, 90, 92, + 94, 99, 103, 104, 107, 107, 107, 107, 110, 113, + 114, 116, 118, 120, 121, 122, 123, 124, 127, 131, + 132, 133, 136, 137, 138, 140, 160, 162, 163, 164, + 165, 166, 167, 168, 169, 136, 171, 179, 180, 181, + 182, 183, 192, 196, 197, 198, 199, 200, 202, 210, + 211, 212, 192, 85, 196, 221, 222, 223, 225, 85, + 227, 228, 231, 85 ] racc_action_check = [ - 42, 130, 42, 130, 129, 130, 159, 177, 159, 177, - 159, 177, 193, 2, 193, 2, 193, 130, 187, 26, - 129, 26, 159, 177, 26, 187, 187, 187, 193, 1, - 27, 9, 27, 3, 27, 27, 7, 14, 130, 14, - 13, 42, 35, 159, 177, 15, 57, 35, 57, 193, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 16, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 4, 58, 17, 58, 4, 4, 4, 4, 4, - 4, 18, 19, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 28, 29, 28, 29, - 21, 28, 29, 30, 31, 30, 31, 23, 30, 31, - 154, 69, 154, 69, 154, 154, 155, 70, 155, 70, - 155, 155, 156, 96, 156, 96, 156, 156, 170, 98, - 170, 98, 170, 170, 174, 104, 174, 104, 174, 174, - 175, 106, 175, 106, 175, 175, 62, 63, 62, 63, - 62, 63, 101, 103, 101, 103, 101, 103, 123, 148, - 123, 148, 123, 148, 160, 189, 160, 189, 160, 189, - 191, 196, 191, 196, 191, 196, 146, 146, 146, 146, - 120, 124, 120, 124, 125, 179, 125, 179, 202, 24, - 202, 25, 32, 33, 38, 39, 46, 48, 49, 50, - 56, 60, 61, 68, 73, 74, 75, 76, 82, 83, - 89, 91, 92, 93, 94, 95, 99, 107, 108, 109, - 110, 111, 112, 114, 134, 136, 137, 138, 139, 140, - 141, 142, 143, 145, 149, 151, 157, 162, 166, 176, - 185, 186, 190, 192, 197, 201, 206, 207 ] + 43, 135, 43, 135, 119, 135, 1, 3, 170, 134, + 170, 64, 170, 64, 191, 64, 191, 135, 191, 213, + 7, 213, 119, 213, 170, 134, 27, 2, 27, 2, + 191, 27, 28, 13, 28, 213, 28, 28, 9, 135, + 135, 135, 135, 15, 16, 43, 170, 170, 170, 170, + 36, 29, 191, 29, 17, 36, 29, 213, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 4, 14, 20, 14, 4, 4, 4, 4, 4, 4, + 22, 24, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 204, 30, 31, 30, + 31, 25, 30, 31, 26, 33, 204, 204, 204, 32, + 59, 32, 59, 165, 32, 165, 34, 165, 165, 166, + 60, 166, 60, 166, 166, 167, 71, 167, 71, 167, + 167, 184, 72, 184, 72, 184, 184, 188, 99, 188, + 99, 188, 188, 189, 101, 189, 101, 189, 189, 65, + 104, 65, 104, 65, 104, 106, 128, 106, 128, 106, + 128, 155, 171, 155, 171, 155, 171, 206, 208, 206, + 208, 206, 208, 216, 107, 216, 107, 216, 153, 153, + 153, 153, 109, 125, 109, 125, 129, 130, 129, 130, + 193, 224, 193, 224, 39, 40, 47, 49, 50, 51, + 53, 58, 62, 63, 70, 75, 76, 77, 78, 84, + 85, 91, 93, 94, 95, 96, 97, 98, 102, 110, + 111, 112, 113, 114, 115, 117, 139, 141, 143, 144, + 145, 146, 147, 148, 149, 150, 152, 156, 157, 158, + 159, 161, 168, 173, 177, 179, 180, 181, 190, 198, + 199, 200, 202, 203, 207, 209, 210, 212, 217, 221, + 222, 223, 230, 231 ] racc_action_pointer = [ - nil, 29, 3, 33, 62, nil, nil, 29, nil, 27, - nil, nil, nil, 34, 34, 26, 41, 54, 76, 63, - nil, 81, nil, 88, 170, 172, 16, 27, 93, 94, - 100, 101, 187, 191, nil, 38, nil, nil, 172, 151, - nil, nil, -5, nil, nil, nil, 177, nil, 178, 179, - 180, nil, nil, nil, nil, nil, 192, 43, 69, nil, - 195, 194, 143, 144, nil, nil, nil, nil, 195, 108, - 114, nil, nil, 196, 197, 198, 173, nil, nil, nil, - nil, nil, 172, 204, nil, nil, nil, nil, nil, 208, - nil, 209, 210, 211, 212, 213, 120, nil, 126, 209, - nil, 149, nil, 150, 132, nil, 138, 212, 207, 217, - 181, 176, 220, nil, 221, nil, nil, nil, nil, nil, - 177, nil, nil, 155, 178, 149, nil, nil, nil, -18, - -2, nil, nil, nil, 204, nil, 205, 206, 207, 208, - 209, 194, 226, 193, nil, 199, 135, nil, 156, 214, - nil, 215, nil, nil, 107, 113, 119, 197, nil, 3, - 161, nil, 229, nil, nil, nil, 236, nil, nil, nil, - 125, nil, nil, nil, 131, 137, 201, 4, nil, 150, - nil, nil, nil, nil, nil, 201, 197, -16, nil, 162, - 234, 167, 223, 9, nil, nil, 168, 242, nil, nil, - nil, 201, 153, nil, nil, nil, 226, 203, nil ] + nil, 6, 17, 7, 71, nil, nil, 13, nil, 34, + nil, nil, nil, 27, 78, 24, 25, 35, 63, 50, + 77, nil, 71, nil, 72, 92, 95, 23, 29, 48, + 104, 105, 116, 110, 124, nil, 46, nil, nil, 181, + 157, nil, nil, -5, nil, nil, nil, 187, nil, 188, + 189, 190, nil, 191, nil, nil, nil, nil, 203, 117, + 127, nil, 206, 205, 8, 156, nil, nil, nil, nil, + 206, 133, 139, nil, nil, 207, 208, 209, 183, nil, + nil, nil, nil, nil, 182, 215, nil, nil, nil, nil, + nil, 219, nil, 220, 218, 222, 223, 224, 225, 145, + nil, 151, 221, nil, 157, nil, 162, 181, nil, 189, + 224, 219, 229, 192, 184, 232, nil, 233, nil, -16, + nil, nil, nil, nil, nil, 190, nil, nil, 163, 193, + 161, nil, nil, nil, -14, -2, nil, nil, nil, 216, + nil, 217, nil, 233, 219, 220, 221, 222, 206, 239, + 205, nil, 211, 143, nil, 168, 212, 213, 214, 230, + nil, 231, nil, nil, nil, 120, 126, 132, 212, nil, + 5, 169, nil, 245, nil, nil, nil, 252, nil, 250, + 251, 252, nil, nil, 138, nil, nil, nil, 144, 150, + 219, 11, nil, 164, nil, nil, nil, nil, 221, 224, + 223, nil, 222, 215, 71, nil, 174, 256, 175, 245, + 261, nil, 262, 16, nil, nil, 180, 266, nil, nil, + nil, 221, 234, 235, 165, nil, nil, nil, nil, nil, + 252, 225, nil ] racc_action_default = [ - -2, -128, -8, -128, -128, -3, -4, -128, 209, -128, - -9, -10, -11, -128, -128, -128, -128, -128, -128, -128, - -23, -128, -27, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -7, -113, -88, -90, -128, -110, - -112, -12, -117, -86, -87, -116, -14, -77, -15, -16, - -128, -20, -24, -28, -31, -34, -37, -43, -128, -46, - -63, -38, -67, -128, -70, -72, -73, -125, -39, -80, - -128, -83, -85, -40, -41, -42, -128, -5, -1, -89, - -114, -91, -128, -128, -13, -118, -119, -120, -74, -128, - -17, -128, -128, -128, -128, -128, -128, -47, -44, -65, - -64, -128, -71, -68, -128, -84, -81, -128, -128, -128, - -96, -128, -128, -78, -128, -21, -25, -29, -32, -35, - -45, -48, -66, -69, -82, -128, -50, -6, -115, -92, - -93, -97, -111, -75, -128, -18, -128, -128, -128, -128, - -128, -128, -128, -96, -95, -86, -110, -101, -128, -128, - -79, -128, -22, -26, -128, -128, -128, -54, -51, -94, - -128, -98, -126, -105, -106, -107, -128, -104, -76, -19, - -30, -121, -123, -124, -33, -36, -49, -52, -55, -128, - -108, -99, -127, -102, -122, -54, -110, -86, -59, -128, - -126, -128, -128, -53, -56, -57, -128, -128, -62, -100, - -109, -110, -128, -60, -103, -58, -128, -110, -61 ] + -2, -134, -8, -134, -134, -3, -4, -134, 233, -134, + -9, -10, -11, -134, -134, -134, -134, -134, -134, -134, + -134, -24, -134, -28, -134, -134, -134, -134, -134, -134, + -134, -134, -134, -134, -134, -7, -117, -89, -91, -134, + -114, -116, -12, -121, -87, -88, -120, -14, -78, -15, + -16, -134, -20, -134, -25, -29, -32, -35, -38, -44, + -134, -47, -64, -39, -68, -134, -71, -73, -74, -131, + -40, -81, -134, -84, -86, -41, -42, -43, -134, -5, + -1, -90, -118, -92, -134, -134, -13, -122, -123, -124, + -75, -134, -17, -134, -134, -134, -134, -134, -134, -134, + -48, -45, -66, -65, -134, -72, -69, -134, -85, -82, + -134, -134, -134, -97, -134, -134, -79, -134, -21, -134, + -129, -26, -30, -33, -36, -46, -49, -67, -70, -83, + -134, -51, -6, -119, -93, -94, -98, -115, -76, -134, + -18, -134, -23, -134, -134, -134, -134, -134, -134, -134, + -97, -96, -87, -114, -102, -134, -134, -134, -134, -134, + -80, -134, -22, -130, -27, -134, -134, -134, -55, -52, + -95, -134, -99, -132, -109, -110, -111, -134, -105, -134, + -134, -134, -77, -19, -31, -125, -127, -128, -34, -37, + -50, -53, -56, -134, -112, -100, -133, -103, -134, -134, + -134, -126, -55, -114, -87, -60, -134, -132, -134, -134, + -134, -107, -134, -54, -57, -58, -134, -134, -63, -101, + -113, -114, -134, -134, -134, -61, -104, -106, -108, -59, + -134, -114, -62 ] racc_goto_table = [ - 64, 45, 57, 62, 105, 82, 97, 162, 106, 177, - 179, 1, 181, 60, 2, 72, 72, 72, 72, 130, - 184, 4, 35, 36, 184, 184, 68, 73, 74, 75, - 46, 48, 49, 78, 98, 102, 64, 193, 5, 103, - 199, 105, 124, 33, 60, 60, 202, 97, 195, 79, - 108, 10, 159, 170, 174, 175, 72, 72, 11, 105, - 12, 42, 84, 114, 151, 91, 136, 92, 137, 97, - 93, 138, 120, 94, 64, 139, 102, 123, 95, 140, - 56, 61, 99, 60, 121, 60, 125, 176, 197, 206, - 112, 72, 149, 72, 89, 134, 102, 129, 166, 192, - 109, nil, nil, 146, nil, nil, nil, 60, nil, nil, - nil, 72, 161, nil, nil, nil, nil, nil, nil, nil, - nil, 167, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 146, 180, nil, nil, nil, nil, nil, nil, + 84, 46, 66, 64, 59, 108, 100, 193, 135, 173, + 191, 47, 49, 50, 62, 109, 74, 74, 74, 74, + 195, 201, 37, 1, 2, 201, 201, 70, 75, 76, + 77, 184, 188, 189, 4, 36, 80, 101, 105, 66, + 106, 5, 34, 108, 213, 170, 62, 62, 100, 81, + 129, 111, 224, 10, 219, 11, 12, 43, 74, 74, + 215, 86, 119, 108, 117, 161, 93, 141, 95, 144, + 96, 145, 100, 97, 146, 98, 125, 147, 66, 128, + 105, 58, 63, 102, 126, 130, 62, 190, 62, 217, + 230, 115, 159, 91, 74, 139, 74, 134, 177, 209, + 112, nil, 105, nil, nil, nil, nil, nil, nil, 153, + nil, nil, 62, 172, nil, nil, 74, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 178, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 186, nil, 194, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 198, nil, 200, nil, 186, 204, nil, 180, - nil, nil, nil, 208 ] + nil, nil, nil, nil, 153, 194, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, 214, nil, 203, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 218, 226, 220, nil, nil, nil, nil, 203, nil, nil, + 194, 232 ] racc_goto_check = [ - 40, 34, 32, 46, 53, 41, 33, 42, 52, 39, - 43, 1, 59, 34, 2, 34, 34, 34, 34, 58, - 63, 3, 4, 54, 63, 63, 31, 31, 31, 31, - 14, 14, 14, 5, 32, 40, 40, 39, 6, 46, - 59, 53, 52, 7, 34, 34, 43, 33, 42, 54, - 8, 9, 58, 20, 20, 20, 34, 34, 10, 53, - 11, 12, 13, 15, 16, 17, 18, 21, 22, 33, - 23, 24, 32, 25, 40, 26, 40, 46, 27, 28, - 29, 30, 35, 34, 36, 34, 37, 38, 44, 45, - 48, 34, 49, 34, 50, 51, 40, 57, 60, 61, - 62, nil, nil, 40, nil, nil, nil, 34, nil, nil, - nil, 34, 41, nil, nil, nil, nil, nil, nil, nil, - nil, 40, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 40, 40, nil, nil, nil, nil, nil, nil, + 42, 35, 41, 47, 33, 54, 34, 44, 59, 43, + 40, 14, 14, 14, 35, 53, 35, 35, 35, 35, + 60, 64, 55, 1, 2, 64, 64, 32, 32, 32, + 32, 21, 21, 21, 3, 4, 5, 33, 41, 41, + 47, 6, 7, 54, 40, 59, 35, 35, 34, 55, + 53, 8, 44, 9, 60, 10, 11, 12, 35, 35, + 43, 13, 15, 54, 16, 17, 18, 19, 22, 23, + 24, 25, 34, 26, 27, 28, 33, 29, 41, 47, + 41, 30, 31, 36, 37, 38, 35, 39, 35, 45, + 46, 49, 50, 51, 35, 52, 35, 58, 61, 62, + 63, nil, 41, nil, nil, nil, nil, nil, nil, 41, + nil, nil, 35, 42, nil, nil, 35, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 41, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, 41, 41, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, 42, nil, 41, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 40, nil, 41, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 40, nil, 40, nil, 40, 41, nil, 40, - nil, nil, nil, 41 ] + 41, 42, 41, nil, nil, nil, nil, 41, nil, nil, + 41, 42 ] racc_goto_pointer = [ - nil, 11, 14, 19, 13, -2, 36, 37, -27, 47, - 54, 56, 47, 20, 15, -27, -71, 14, -49, nil, - -101, 15, -48, 17, -46, 19, -43, 23, -40, 54, - 54, -2, -24, -51, -13, 22, -15, -21, -70, -148, - -27, -34, -139, -150, -100, -114, -24, nil, 2, -41, - 47, -18, -62, -65, 14, nil, nil, -13, -91, -150, - -49, -84, 20, -150 ] + nil, 23, 24, 32, 26, 0, 39, 36, -28, 49, + 51, 52, 43, 18, -4, -32, -28, -75, 14, -51, + nil, -134, 14, -52, 15, -51, 17, -49, 18, -47, + 54, 54, -2, -23, -53, -13, 21, -18, -25, -81, + -158, -26, -40, -144, -164, -116, -135, -25, nil, 1, + -46, 45, -21, -57, -66, 13, nil, nil, -16, -105, + -153, -56, -98, 18, -163 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 38, nil, nil, nil, nil, nil, nil, nil, nil, 22, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 59, 65, nil, nil, nil, nil, nil, - 172, nil, nil, nil, nil, nil, nil, 66, nil, nil, - nil, nil, 69, 71, nil, 37, 39, nil, nil, nil, - nil, nil, nil, 171 ] + 39, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 23, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, 61, 67, nil, nil, nil, nil, + nil, 186, nil, nil, nil, nil, nil, nil, 68, nil, + nil, nil, nil, 71, 73, nil, 38, 40, nil, nil, + nil, nil, nil, nil, 185 ] racc_reduce_table = [ 0, 0, :racc_error, - 5, 48, :_reduce_none, - 0, 49, :_reduce_none, - 2, 49, :_reduce_none, - 0, 54, :_reduce_4, - 0, 55, :_reduce_5, - 5, 53, :_reduce_6, + 5, 52, :_reduce_none, + 0, 53, :_reduce_none, 2, 53, :_reduce_none, - 0, 50, :_reduce_8, - 2, 50, :_reduce_none, - 1, 56, :_reduce_none, - 1, 56, :_reduce_none, - 2, 56, :_reduce_12, - 3, 56, :_reduce_none, - 2, 56, :_reduce_none, - 2, 56, :_reduce_15, - 2, 56, :_reduce_16, - 0, 62, :_reduce_17, - 0, 63, :_reduce_18, - 7, 56, :_reduce_19, - 0, 64, :_reduce_20, - 0, 65, :_reduce_21, - 6, 56, :_reduce_22, - 1, 56, :_reduce_none, - 0, 68, :_reduce_24, - 0, 69, :_reduce_25, - 6, 57, :_reduce_26, - 1, 57, :_reduce_none, - 0, 70, :_reduce_28, - 0, 71, :_reduce_29, - 7, 57, :_reduce_none, - 0, 72, :_reduce_31, - 0, 73, :_reduce_32, - 7, 57, :_reduce_33, - 0, 74, :_reduce_34, - 0, 75, :_reduce_35, - 7, 57, :_reduce_36, - 2, 66, :_reduce_none, - 2, 66, :_reduce_38, - 2, 66, :_reduce_39, - 2, 66, :_reduce_40, - 2, 66, :_reduce_41, - 2, 66, :_reduce_42, - 1, 76, :_reduce_43, - 2, 76, :_reduce_44, - 3, 76, :_reduce_45, - 1, 79, :_reduce_46, - 2, 79, :_reduce_47, - 3, 80, :_reduce_48, - 7, 58, :_reduce_49, - 1, 84, :_reduce_50, - 3, 84, :_reduce_51, - 1, 85, :_reduce_52, - 3, 85, :_reduce_53, - 0, 86, :_reduce_54, - 1, 86, :_reduce_55, - 3, 86, :_reduce_56, - 3, 86, :_reduce_57, - 5, 86, :_reduce_58, - 0, 91, :_reduce_59, - 0, 92, :_reduce_60, - 7, 86, :_reduce_61, - 3, 86, :_reduce_62, - 0, 82, :_reduce_none, - 1, 82, :_reduce_none, - 0, 83, :_reduce_none, - 1, 83, :_reduce_none, - 1, 77, :_reduce_67, - 2, 77, :_reduce_68, - 3, 77, :_reduce_69, - 1, 93, :_reduce_70, - 2, 93, :_reduce_71, - 1, 87, :_reduce_none, - 1, 87, :_reduce_none, - 0, 95, :_reduce_74, - 0, 96, :_reduce_75, - 6, 61, :_reduce_76, - 0, 97, :_reduce_77, - 0, 98, :_reduce_78, - 5, 61, :_reduce_79, - 1, 78, :_reduce_80, - 2, 78, :_reduce_81, - 3, 78, :_reduce_82, - 1, 99, :_reduce_83, - 2, 99, :_reduce_84, - 1, 100, :_reduce_none, - 1, 81, :_reduce_86, - 1, 81, :_reduce_87, - 1, 51, :_reduce_none, - 2, 51, :_reduce_none, - 1, 101, :_reduce_none, - 2, 101, :_reduce_none, - 4, 102, :_reduce_92, - 1, 104, :_reduce_93, - 3, 104, :_reduce_94, - 2, 104, :_reduce_none, - 0, 105, :_reduce_96, - 1, 105, :_reduce_97, - 3, 105, :_reduce_98, - 4, 105, :_reduce_99, - 6, 105, :_reduce_100, - 0, 107, :_reduce_101, - 0, 108, :_reduce_102, - 7, 105, :_reduce_103, - 3, 105, :_reduce_104, - 1, 89, :_reduce_none, - 1, 89, :_reduce_none, - 1, 89, :_reduce_none, - 1, 90, :_reduce_108, - 3, 90, :_reduce_109, - 0, 88, :_reduce_none, - 3, 88, :_reduce_111, - 1, 103, :_reduce_none, - 0, 52, :_reduce_none, - 0, 109, :_reduce_114, - 3, 52, :_reduce_115, - 1, 59, :_reduce_none, - 0, 60, :_reduce_none, + 0, 58, :_reduce_4, + 0, 59, :_reduce_5, + 5, 57, :_reduce_6, + 2, 57, :_reduce_none, + 0, 54, :_reduce_8, + 2, 54, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, + 2, 60, :_reduce_12, + 3, 60, :_reduce_none, + 2, 60, :_reduce_none, + 2, 60, :_reduce_15, + 2, 60, :_reduce_16, + 0, 67, :_reduce_17, + 0, 68, :_reduce_18, + 7, 60, :_reduce_19, + 0, 69, :_reduce_20, + 0, 70, :_reduce_21, + 6, 60, :_reduce_22, + 5, 60, :_reduce_23, 1, 60, :_reduce_none, - 1, 67, :_reduce_121, - 2, 67, :_reduce_122, - 1, 110, :_reduce_none, - 1, 110, :_reduce_none, - 1, 94, :_reduce_125, - 0, 106, :_reduce_none, - 1, 106, :_reduce_none ] - -racc_reduce_n = 128 - -racc_shift_n = 209 + 0, 73, :_reduce_25, + 0, 74, :_reduce_26, + 6, 61, :_reduce_27, + 1, 61, :_reduce_none, + 0, 75, :_reduce_29, + 0, 76, :_reduce_30, + 7, 61, :_reduce_none, + 0, 77, :_reduce_32, + 0, 78, :_reduce_33, + 7, 61, :_reduce_34, + 0, 79, :_reduce_35, + 0, 80, :_reduce_36, + 7, 61, :_reduce_37, + 2, 71, :_reduce_none, + 2, 71, :_reduce_39, + 2, 71, :_reduce_40, + 2, 71, :_reduce_41, + 2, 71, :_reduce_42, + 2, 71, :_reduce_43, + 1, 81, :_reduce_44, + 2, 81, :_reduce_45, + 3, 81, :_reduce_46, + 1, 84, :_reduce_47, + 2, 84, :_reduce_48, + 3, 85, :_reduce_49, + 7, 62, :_reduce_50, + 1, 89, :_reduce_51, + 3, 89, :_reduce_52, + 1, 90, :_reduce_53, + 3, 90, :_reduce_54, + 0, 91, :_reduce_55, + 1, 91, :_reduce_56, + 3, 91, :_reduce_57, + 3, 91, :_reduce_58, + 5, 91, :_reduce_59, + 0, 96, :_reduce_60, + 0, 97, :_reduce_61, + 7, 91, :_reduce_62, + 3, 91, :_reduce_63, + 0, 87, :_reduce_none, + 1, 87, :_reduce_none, + 0, 88, :_reduce_none, + 1, 88, :_reduce_none, + 1, 82, :_reduce_68, + 2, 82, :_reduce_69, + 3, 82, :_reduce_70, + 1, 98, :_reduce_71, + 2, 98, :_reduce_72, + 1, 92, :_reduce_none, + 1, 92, :_reduce_none, + 0, 100, :_reduce_75, + 0, 101, :_reduce_76, + 6, 65, :_reduce_77, + 0, 102, :_reduce_78, + 0, 103, :_reduce_79, + 5, 65, :_reduce_80, + 1, 83, :_reduce_81, + 2, 83, :_reduce_82, + 3, 83, :_reduce_83, + 1, 104, :_reduce_84, + 2, 104, :_reduce_85, + 1, 105, :_reduce_none, + 1, 86, :_reduce_87, + 1, 86, :_reduce_88, + 1, 55, :_reduce_none, + 2, 55, :_reduce_none, + 1, 106, :_reduce_none, + 2, 106, :_reduce_none, + 4, 107, :_reduce_93, + 1, 109, :_reduce_94, + 3, 109, :_reduce_95, + 2, 109, :_reduce_none, + 0, 110, :_reduce_97, + 1, 110, :_reduce_98, + 3, 110, :_reduce_99, + 4, 110, :_reduce_100, + 6, 110, :_reduce_101, + 0, 112, :_reduce_102, + 0, 113, :_reduce_103, + 7, 110, :_reduce_104, + 3, 110, :_reduce_105, + 7, 110, :_reduce_106, + 5, 110, :_reduce_107, + 7, 110, :_reduce_108, + 1, 94, :_reduce_none, + 1, 94, :_reduce_none, + 1, 94, :_reduce_none, + 1, 95, :_reduce_112, + 3, 95, :_reduce_113, + 0, 93, :_reduce_none, + 3, 93, :_reduce_115, + 1, 108, :_reduce_none, + 0, 56, :_reduce_none, + 0, 114, :_reduce_118, + 3, 56, :_reduce_119, + 1, 63, :_reduce_none, + 0, 64, :_reduce_none, + 1, 64, :_reduce_none, + 1, 64, :_reduce_none, + 1, 64, :_reduce_none, + 1, 72, :_reduce_125, + 2, 72, :_reduce_126, + 1, 115, :_reduce_none, + 1, 115, :_reduce_none, + 1, 66, :_reduce_129, + 3, 66, :_reduce_130, + 1, 99, :_reduce_131, + 0, 111, :_reduce_none, + 1, 111, :_reduce_none ] + +racc_reduce_n = 134 + +racc_shift_n = 233 racc_token_table = { false => 0, @@ -1071,33 +1093,37 @@ def carrets(text, first_column, last_column) "{" => 19, "}" => 20, "%initial-action" => 21, - ";" => 22, - "%union" => 23, - "%destructor" => 24, - "%printer" => 25, - "%error-token" => 26, - "%token" => 27, - "%type" => 28, - "%left" => 29, - "%right" => 30, - "%precedence" => 31, - "%nonassoc" => 32, - "%rule" => 33, - "(" => 34, - ")" => 35, - ":" => 36, - "," => 37, - "|" => 38, - "%empty" => 39, - "%prec" => 40, - "?" => 41, - "+" => 42, - "*" => 43, - "[" => 44, - "]" => 45, - "{...}" => 46 } - -racc_nt_base = 47 + "%parser-state" => 22, + ";" => 23, + "%union" => 24, + "%destructor" => 25, + "%printer" => 26, + "%error-token" => 27, + "%token" => 28, + "%type" => 29, + "%left" => 30, + "%right" => 31, + "%precedence" => 32, + "%nonassoc" => 33, + "%rule" => 34, + "(" => 35, + ")" => 36, + ":" => 37, + "," => 38, + "|" => 39, + "%empty" => 40, + "%prec" => 41, + "%parser-state-push" => 42, + "%parser-state-pop" => 43, + "%parser-state-set" => 44, + "?" => 45, + "+" => 46, + "*" => 47, + "[" => 48, + "]" => 49, + "{...}" => 50 } + +racc_nt_base = 51 racc_use_result_var = true @@ -1141,6 +1167,7 @@ def carrets(text, first_column, last_column) "\"{\"", "\"}\"", "\"%initial-action\"", + "\"%parser-state\"", "\";\"", "\"%union\"", "\"%destructor\"", @@ -1160,6 +1187,9 @@ def carrets(text, first_column, last_column) "\"|\"", "\"%empty\"", "\"%prec\"", + "\"%parser-state-push\"", + "\"%parser-state-pop\"", + "\"%parser-state-set\"", "\"?\"", "\"+\"", "\"*\"", @@ -1181,6 +1211,7 @@ def carrets(text, first_column, last_column) "variable", "value", "params", + "identifier_list", "@3", "@4", "@5", @@ -1363,19 +1394,19 @@ def _reduce_22(val, _values, result) end .,., -# reduce 23 omitted - -module_eval(<<'.,.,', 'parser.y', 75) - def _reduce_24(val, _values, result) - begin_c_declaration("}") +module_eval(<<'.,.,', 'parser.y', 73) + def _reduce_23(val, _values, result) + @grammar.add_parser_state(val[1], val[3]) result end .,., +# reduce 24 omitted + module_eval(<<'.,.,', 'parser.y', 79) def _reduce_25(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1383,6 +1414,14 @@ def _reduce_25(val, _values, result) module_eval(<<'.,.,', 'parser.y', 83) def _reduce_26(val, _values, result) + end_c_declaration + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 87) + def _reduce_27(val, _values, result) @grammar.set_union( Grammar::Code::NoReferenceCode.new(type: :union, token_code: val[3]), val[3].line @@ -1392,44 +1431,44 @@ def _reduce_26(val, _values, result) end .,., -# reduce 27 omitted +# reduce 28 omitted -module_eval(<<'.,.,', 'parser.y', 91) - def _reduce_28(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 95) + def _reduce_29(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 95) - def _reduce_29(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 99) + def _reduce_30(val, _values, result) end_c_declaration result end .,., -# reduce 30 omitted +# reduce 31 omitted -module_eval(<<'.,.,', 'parser.y', 100) - def _reduce_31(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 104) + def _reduce_32(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 104) - def _reduce_32(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 108) + def _reduce_33(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 108) - def _reduce_33(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 112) + def _reduce_34(val, _values, result) @grammar.add_printer( ident_or_tags: val[6], token_code: val[3], @@ -1440,24 +1479,24 @@ def _reduce_33(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 116) - def _reduce_34(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 120) + def _reduce_35(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 120) - def _reduce_35(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 124) + def _reduce_36(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 124) - def _reduce_36(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 128) + def _reduce_37(val, _values, result) @grammar.add_error_token( ident_or_tags: val[6], token_code: val[3], @@ -1468,10 +1507,10 @@ def _reduce_36(val, _values, result) end .,., -# reduce 37 omitted +# reduce 38 omitted -module_eval(<<'.,.,', 'parser.y', 134) - def _reduce_38(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 138) + def _reduce_39(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| @grammar.add_type(id: id, tag: hash[:tag]) @@ -1482,8 +1521,8 @@ def _reduce_38(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 142) - def _reduce_39(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 146) + def _reduce_40(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1496,8 +1535,8 @@ def _reduce_39(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 152) - def _reduce_40(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 156) + def _reduce_41(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1510,8 +1549,8 @@ def _reduce_40(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 162) - def _reduce_41(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 166) + def _reduce_42(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1524,8 +1563,8 @@ def _reduce_41(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 172) - def _reduce_42(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 176) + def _reduce_43(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1538,8 +1577,8 @@ def _reduce_42(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 183) - def _reduce_43(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 187) + def _reduce_44(val, _values, result) val[0].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: nil, replace: true) } @@ -1548,8 +1587,8 @@ def _reduce_43(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 189) - def _reduce_44(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 193) + def _reduce_45(val, _values, result) val[1].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[0], replace: true) } @@ -1558,8 +1597,8 @@ def _reduce_44(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 195) - def _reduce_45(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 199) + def _reduce_46(val, _values, result) val[2].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[1], replace: true) } @@ -1568,29 +1607,29 @@ def _reduce_45(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 200) - def _reduce_46(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 204) + def _reduce_47(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 201) - def _reduce_47(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 205) + def _reduce_48(val, _values, result) result = val[0].append(val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 203) - def _reduce_48(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 207) + def _reduce_49(val, _values, result) result = val result end .,., -module_eval(<<'.,.,', 'parser.y', 207) - def _reduce_49(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 211) + def _reduce_50(val, _values, result) builder = Grammar::ParameterizingRuleBuilder.new(val[1].s_value, val[3], val[6]) @grammar.add_parameterizing_rule_builder(builder) @@ -1598,22 +1637,22 @@ def _reduce_49(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 211) - def _reduce_50(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 215) + def _reduce_51(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 212) - def _reduce_51(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 216) + def _reduce_52(val, _values, result) result = val[0].append(val[2]) result end .,., -module_eval(<<'.,.,', 'parser.y', 216) - def _reduce_52(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 220) + def _reduce_53(val, _values, result) builder = val[0] result = [builder] @@ -1621,8 +1660,8 @@ def _reduce_52(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 221) - def _reduce_53(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 225) + def _reduce_54(val, _values, result) builder = val[2] result = val[0].append(builder) @@ -1630,8 +1669,8 @@ def _reduce_53(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 227) - def _reduce_54(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 231) + def _reduce_55(val, _values, result) reset_precs result = Grammar::ParameterizingRuleRhsBuilder.new @@ -1639,8 +1678,8 @@ def _reduce_54(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 232) - def _reduce_55(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 236) + def _reduce_56(val, _values, result) reset_precs result = Grammar::ParameterizingRuleRhsBuilder.new @@ -1648,8 +1687,8 @@ def _reduce_55(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 237) - def _reduce_56(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 241) + def _reduce_57(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1660,8 +1699,8 @@ def _reduce_56(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 245) - def _reduce_57(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 249) + def _reduce_58(val, _values, result) builder = val[0] builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]]) result = builder @@ -1670,8 +1709,8 @@ def _reduce_57(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 251) - def _reduce_58(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 255) + def _reduce_59(val, _values, result) builder = val[0] builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3]) result = builder @@ -1680,8 +1719,8 @@ def _reduce_58(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 257) - def _reduce_59(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 261) + def _reduce_60(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1692,16 +1731,16 @@ def _reduce_59(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 265) - def _reduce_60(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 269) + def _reduce_61(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 269) - def _reduce_61(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 273) + def _reduce_62(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -1712,8 +1751,8 @@ def _reduce_61(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 277) - def _reduce_62(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 281) + def _reduce_63(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -1724,67 +1763,59 @@ def _reduce_62(val, _values, result) end .,., -# reduce 63 omitted - # reduce 64 omitted # reduce 65 omitted # reduce 66 omitted -module_eval(<<'.,.,', 'parser.y', 292) - def _reduce_67(val, _values, result) +# reduce 67 omitted + +module_eval(<<'.,.,', 'parser.y', 296) + def _reduce_68(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 296) - def _reduce_68(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 300) + def _reduce_69(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 300) - def _reduce_69(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 304) + def _reduce_70(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 303) - def _reduce_70(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 307) + def _reduce_71(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 304) - def _reduce_71(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 308) + def _reduce_72(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 72 omitted - # reduce 73 omitted -module_eval(<<'.,.,', 'parser.y', 311) - def _reduce_74(val, _values, result) - begin_c_declaration("}") - - result - end -.,., +# reduce 74 omitted module_eval(<<'.,.,', 'parser.y', 315) def _reduce_75(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1792,7 +1823,7 @@ def _reduce_75(val, _values, result) module_eval(<<'.,.,', 'parser.y', 319) def _reduce_76(val, _values, result) - result = val[0].append(val[3]) + end_c_declaration result end @@ -1800,7 +1831,7 @@ def _reduce_76(val, _values, result) module_eval(<<'.,.,', 'parser.y', 323) def _reduce_77(val, _values, result) - begin_c_declaration("}") + result = val[0].append(val[3]) result end @@ -1808,7 +1839,7 @@ def _reduce_77(val, _values, result) module_eval(<<'.,.,', 'parser.y', 327) def _reduce_78(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1816,15 +1847,15 @@ def _reduce_78(val, _values, result) module_eval(<<'.,.,', 'parser.y', 331) def _reduce_79(val, _values, result) - result = [val[2]] + end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 336) +module_eval(<<'.,.,', 'parser.y', 335) def _reduce_80(val, _values, result) - result = [{tag: nil, tokens: val[0]}] + result = [val[2]] result end @@ -1832,7 +1863,7 @@ def _reduce_80(val, _values, result) module_eval(<<'.,.,', 'parser.y', 340) def _reduce_81(val, _values, result) - result = [{tag: val[0], tokens: val[1]}] + result = [{tag: nil, tokens: val[0]}] result end @@ -1840,52 +1871,60 @@ def _reduce_81(val, _values, result) module_eval(<<'.,.,', 'parser.y', 344) def _reduce_82(val, _values, result) - result = val[0].append({tag: val[1], tokens: val[2]}) + result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 347) +module_eval(<<'.,.,', 'parser.y', 348) def _reduce_83(val, _values, result) - result = [val[0]] + result = val[0].append({tag: val[1], tokens: val[2]}) + result end .,., -module_eval(<<'.,.,', 'parser.y', 348) +module_eval(<<'.,.,', 'parser.y', 351) def _reduce_84(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 352) + def _reduce_85(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 85 omitted +# reduce 86 omitted -module_eval(<<'.,.,', 'parser.y', 352) - def _reduce_86(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 356) + def _reduce_87(val, _values, result) on_action_error("ident after %prec", val[0]) if @prec_seen result end .,., -module_eval(<<'.,.,', 'parser.y', 353) - def _reduce_87(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 357) + def _reduce_88(val, _values, result) on_action_error("char after %prec", val[0]) if @prec_seen result end .,., -# reduce 88 omitted - # reduce 89 omitted # reduce 90 omitted # reduce 91 omitted -module_eval(<<'.,.,', 'parser.y', 363) - def _reduce_92(val, _values, result) +# reduce 92 omitted + +module_eval(<<'.,.,', 'parser.y', 367) + def _reduce_93(val, _values, result) lhs = val[0] lhs.alias_name = val[1] val[3].each do |builder| @@ -1898,8 +1937,8 @@ def _reduce_92(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 374) - def _reduce_93(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 378) + def _reduce_94(val, _values, result) builder = val[0] if !builder.line builder.line = @lexer.line - 1 @@ -1910,8 +1949,8 @@ def _reduce_93(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 382) - def _reduce_94(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 386) + def _reduce_95(val, _values, result) builder = val[2] if !builder.line builder.line = @lexer.line - 1 @@ -1922,10 +1961,10 @@ def _reduce_94(val, _values, result) end .,., -# reduce 95 omitted +# reduce 96 omitted -module_eval(<<'.,.,', 'parser.y', 392) - def _reduce_96(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 396) + def _reduce_97(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1933,8 +1972,8 @@ def _reduce_96(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 397) - def _reduce_97(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 401) + def _reduce_98(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1942,8 +1981,8 @@ def _reduce_97(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 402) - def _reduce_98(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 406) + def _reduce_99(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1954,8 +1993,8 @@ def _reduce_98(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 410) - def _reduce_99(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 414) + def _reduce_100(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]]) builder = val[0] builder.add_rhs(token) @@ -1967,8 +2006,8 @@ def _reduce_99(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 419) - def _reduce_100(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 423) + def _reduce_101(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3]) builder = val[0] builder.add_rhs(token) @@ -1980,8 +2019,8 @@ def _reduce_100(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 428) - def _reduce_101(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 432) + def _reduce_102(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1992,16 +2031,16 @@ def _reduce_101(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 436) - def _reduce_102(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 440) + def _reduce_103(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 440) - def _reduce_103(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 444) + def _reduce_104(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -2012,8 +2051,8 @@ def _reduce_103(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 448) - def _reduce_104(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 452) + def _reduce_105(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -2024,41 +2063,76 @@ def _reduce_104(val, _values, result) end .,., -# reduce 105 omitted +module_eval(<<'.,.,', 'parser.y', 460) + def _reduce_106(val, _values, result) + token = Lrama::Lexer::Token::ParserStatePush.new(s_value: val[3].s_value, location: val[3].location) + token.state = val[5] + builder = val[0] + builder.add_rhs(token) + result = builder + + result + end +.,., -# reduce 106 omitted +module_eval(<<'.,.,', 'parser.y', 468) + def _reduce_107(val, _values, result) + token = Lrama::Lexer::Token::ParserStatePop.new(s_value: val[3].s_value, location: val[3].location) + builder = val[0] + builder.add_rhs(token) + result = builder -# reduce 107 omitted + result + end +.,., -module_eval(<<'.,.,', 'parser.y', 459) +module_eval(<<'.,.,', 'parser.y', 475) def _reduce_108(val, _values, result) + token = Lrama::Lexer::Token::ParserStateSet.new(s_value: val[3].s_value, location: val[3].location) + token.state = val[5] + builder = val[0] + builder.add_rhs(token) + result = builder + + result + end +.,., + +# reduce 109 omitted + +# reduce 110 omitted + +# reduce 111 omitted + +module_eval(<<'.,.,', 'parser.y', 486) + def _reduce_112(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 460) - def _reduce_109(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 487) + def _reduce_113(val, _values, result) result = val[0].append(val[2]) result end .,., -# reduce 110 omitted +# reduce 114 omitted -module_eval(<<'.,.,', 'parser.y', 463) - def _reduce_111(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 490) + def _reduce_115(val, _values, result) result = val[1].s_value result end .,., -# reduce 112 omitted +# reduce 116 omitted -# reduce 113 omitted +# reduce 117 omitted -module_eval(<<'.,.,', 'parser.y', 470) - def _reduce_114(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 497) + def _reduce_118(val, _values, result) begin_c_declaration('\Z') @grammar.epilogue_first_lineno = @lexer.line + 1 @@ -2066,8 +2140,8 @@ def _reduce_114(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 475) - def _reduce_115(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 502) + def _reduce_119(val, _values, result) end_c_declaration @grammar.epilogue = val[2].s_value @@ -2075,44 +2149,58 @@ def _reduce_115(val, _values, result) end .,., -# reduce 116 omitted +# reduce 120 omitted -# reduce 117 omitted +# reduce 121 omitted -# reduce 118 omitted +# reduce 122 omitted -# reduce 119 omitted +# reduce 123 omitted -# reduce 120 omitted +# reduce 124 omitted -module_eval(<<'.,.,', 'parser.y', 486) - def _reduce_121(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 513) + def _reduce_125(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 487) - def _reduce_122(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 514) + def _reduce_126(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 123 omitted +# reduce 127 omitted -# reduce 124 omitted +# reduce 128 omitted -module_eval(<<'.,.,', 'parser.y', 492) - def _reduce_125(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 519) + def _reduce_129(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 520) + def _reduce_130(val, _values, result) + result = val[0].append(val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 522) + def _reduce_131(val, _values, result) result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) result end .,., -# reduce 126 omitted +# reduce 132 omitted -# reduce 127 omitted +# reduce 133 omitted def _reduce_none(val, _values, result) val[0] diff --git a/parser.y b/parser.y index a2dc03f2..f171d5f9 100644 --- a/parser.y +++ b/parser.y @@ -69,6 +69,10 @@ rule { @grammar.initial_action = Grammar::Code::InitialActionCode.new(type: :initial_action, token_code: val[3]) } + | "%parser-state" IDENTIFIER "{" identifier_list "}" + { + @grammar.add_parser_state(val[1], val[3]) + } | ";" grammar_declaration: "%union" "{" @@ -452,6 +456,29 @@ rule builder.precedence_sym = sym result = builder } + | rhs "%parser-state-push" "(" IDENTIFIER "," IDENTIFIER ")" + { + token = Lrama::Lexer::Token::ParserStatePush.new(s_value: val[3].s_value, location: val[3].location) + token.state = val[5] + builder = val[0] + builder.add_rhs(token) + result = builder + } + | rhs "%parser-state-pop" "(" IDENTIFIER ")" + { + token = Lrama::Lexer::Token::ParserStatePop.new(s_value: val[3].s_value, location: val[3].location) + builder = val[0] + builder.add_rhs(token) + result = builder + } + | rhs "%parser-state-set" "(" IDENTIFIER "," IDENTIFIER ")" + { + token = Lrama::Lexer::Token::ParserStateSet.new(s_value: val[3].s_value, location: val[3].location) + token.state = val[5] + builder = val[0] + builder.add_rhs(token) + result = builder + } parameterizing_suffix: "?" | "+" @@ -490,6 +517,9 @@ rule generic_symlist_item: symbol | TAG + identifier_list: IDENTIFIER { result = [val[0]] } + | identifier_list "," IDENTIFIER { result = val[0].append(val[2]) } + string_as_id: STRING { result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) } tag_opt: # empty diff --git a/sig/lrama/grammar.rbs b/sig/lrama/grammar.rbs index 241a09a1..e38092b9 100644 --- a/sig/lrama/grammar.rbs +++ b/sig/lrama/grammar.rbs @@ -1,5 +1,7 @@ module Lrama class Grammar + attr_reader parser_states: Array[ParserState] + def numberize_references: (Lexer::Token lhs, Array[Lexer::Token] rhs, Array[Reference]) -> void end end diff --git a/sig/lrama/grammar/parser_state.rbs b/sig/lrama/grammar/parser_state.rbs new file mode 100644 index 00000000..05e16f85 --- /dev/null +++ b/sig/lrama/grammar/parser_state.rbs @@ -0,0 +1,27 @@ +module Lrama + class Grammar + class ParserState + attr_reader state_id: Lexer::Token::Ident + attr_reader state_list: Array[Lexer::Token::Ident] + + def initialize: (state_id: Lexer::Token::Ident, state_list: Array[Lexer::Token::Ident]) -> void + + def enum_definition: () -> String + def state_name_macro: () -> String + def current_state_name_macro: () -> String + def states_functions: () -> String + def states_stack_size_name: () -> String + def states_stacks: () -> String + def state_name: () -> String + def enum_name: () -> String + def enum_type: () -> String + def enum_body: () -> String + def int_to_name: () -> Array[String] + def enum_name_table_name: () -> String + def stack_prefix: () -> String + + private + def enum_numbers:() -> Array[String] + end + end +end diff --git a/sig/lrama/grammar/reference.rbs b/sig/lrama/grammar/reference.rbs index e1b781d7..a27cbac9 100644 --- a/sig/lrama/grammar/reference.rbs +++ b/sig/lrama/grammar/reference.rbs @@ -3,6 +3,7 @@ module Lrama class Reference attr_accessor type: ::Symbol attr_accessor name: String + attr_accessor number: Integer attr_accessor index: Integer attr_accessor ex_tag: Lexer::Token? attr_accessor first_column: Integer @@ -10,7 +11,7 @@ module Lrama attr_accessor position_in_rhs: Integer? def initialize: ( - type: ::Symbol, ?name: String, ?index: Integer, ?ex_tag: Lexer::Token?, + type: ::Symbol, ?name: String, ?number: Integer, ?index: Integer, ?ex_tag: Lexer::Token?, first_column: Integer, last_column: Integer, ?position_in_rhs: Integer? ) -> void diff --git a/sig/lrama/grammar/rule_builder.rbs b/sig/lrama/grammar/rule_builder.rbs index 7522c77f..aa79ba71 100644 --- a/sig/lrama/grammar/rule_builder.rbs +++ b/sig/lrama/grammar/rule_builder.rbs @@ -35,7 +35,11 @@ module Lrama def preprocess_references: () -> void def build_rules: () -> void def process_rhs: (Grammar::ParameterizingRuleResolver parameterizing_resolver) -> void + def process_parser_state_token: (Lexer::Token, String, String, Integer, Grammar::ParameterizingRuleResolver) -> void def numberize_references: () -> void + def referable_token?: (Lexer::Token) -> bool + def referable_tokens: () -> Array[Lexer::Token] + def number_to_index: () -> Array[Integer] def flush_user_code: () -> void end end diff --git a/sig/lrama/lexer/token/parser_state_pop.rbs b/sig/lrama/lexer/token/parser_state_pop.rbs new file mode 100644 index 00000000..ac2c020b --- /dev/null +++ b/sig/lrama/lexer/token/parser_state_pop.rbs @@ -0,0 +1,8 @@ +module Lrama + class Lexer + class Token + class ParserStatePop < Token + end + end + end +end diff --git a/sig/lrama/lexer/token/parser_state_push.rbs b/sig/lrama/lexer/token/parser_state_push.rbs new file mode 100644 index 00000000..a68f10f3 --- /dev/null +++ b/sig/lrama/lexer/token/parser_state_push.rbs @@ -0,0 +1,9 @@ +module Lrama + class Lexer + class Token + class ParserStatePush < Token + attr_accessor state: Token + end + end + end +end diff --git a/sig/lrama/lexer/token/parser_state_set.rbs b/sig/lrama/lexer/token/parser_state_set.rbs new file mode 100644 index 00000000..181f3131 --- /dev/null +++ b/sig/lrama/lexer/token/parser_state_set.rbs @@ -0,0 +1,9 @@ +module Lrama + class Lexer + class Token + class ParserStateSet < Token + attr_accessor state: Token + end + end + end +end diff --git a/spec/fixtures/integration/parser_state.l b/spec/fixtures/integration/parser_state.l new file mode 100644 index 00000000..899934dc --- /dev/null +++ b/spec/fixtures/integration/parser_state.l @@ -0,0 +1,85 @@ +%option noinput nounput noyywrap never-interactive yylineno bison-bridge bison-locations + +%{ + +#include +#include +#include "parser_state.h" + +int yycolumn = 0; + +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line = yylineno; \ + yylloc->first_column = yycolumn; \ + yylloc->last_column = yycolumn + yyleng; \ + yycolumn += yyleng; \ + +%} + +NUMBER [0-9]+ + +%% + +{NUMBER} { + yylval->i = atoi(yytext); + return NUM; +} + +[+\-\*\/\(\)] { + return yytext[0]; +} + +[\n|\r\n] {} + +[[:space:]] {} + +"begin" { + return keyword_begin; +} + +"end" { + return keyword_end; +} + +"rescue" { + return keyword_rescue; +} + +"else" { + return keyword_else; +} + +"ensure" { + return keyword_ensure; +} + +"class" { + return keyword_class; +} + +"def" { + return keyword_def; +} + +[A-Z]+ { + yylval->str = strdup(yytext); + fprintf(stderr, "%s\n", yytext); + return cname; +} + +[a-z][a-z0-9]+ { + yylval->str = strdup(yytext); + fprintf(stderr, "%s\n", yytext); + return fname; +} + +<> { + return(YYEOF); +} + +. { + fprintf(stderr, "Illegal character '%s'\n", yytext); + return(YYEOF); +} + +%% diff --git a/spec/fixtures/integration/parser_state.y b/spec/fixtures/integration/parser_state.y new file mode 100644 index 00000000..59760c02 --- /dev/null +++ b/spec/fixtures/integration/parser_state.y @@ -0,0 +1,130 @@ +%{ + +#define YYDEBUG 1 + +#include +#include "parser_state.h" +#include "parser_state-lexer.h" + +static int yyerror(YYLTYPE *loc, const char *str); + +%} + +%union { + int i; + char *str; +} + +%expect 0 + +%parser-state in_rescue { before_rescue, after_rescue, after_else, after_ensure } +%parser-state in_def { in_def, not_in_def } +%parser-state in_class { in_class, not_in_class } + +%token keyword_begin keyword_end keyword_rescue keyword_else keyword_ensure keyword_class keyword_def +%token NUM +%token cname fname +%token tLSHFT "<<" + +%% + +program : %parser-state-set(in_rescue, before_rescue) + %parser-state-set(in_def, not_in_def) + %parser-state-set(in_class, not_in_class) + { + printf("0 => in_def: %s, in_class: %s.\n", YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + { + printf("0 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); + } + bodystmt + { + printf("1 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); + } + ; + +bodystmt : compstmt + { printf("2 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + opt_rescue + { printf("3 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + opt_else + { printf("4 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + opt_ensure + { printf("5 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + ; + +opt_rescue : keyword_rescue %parser-state-push(in_rescue, after_rescue) + { printf("6 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + compstmt %parser-state-pop(in_rescue) + { printf("7 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + | /* empty */ + ; + +opt_else : keyword_else %parser-state-set(in_rescue, after_else) compstmt + | /* empty */ + ; + +opt_ensure : keyword_ensure %parser-state-set(in_rescue, after_ensure) compstmt + | /* empty */ + ; + +compstmt : stmts + ; + +stmts : /* empty */ + | stmt + | stmts ';' stmt + ; + +stmt : primary + | keyword_begin bodystmt keyword_end + ; + +primary : NUM { printf("NUM => %d\n", $1); } + | keyword_class + %parser-state-push(in_def, not_in_def) + %parser-state-push(in_class, in_class) + cname + { + printf("1. cname => %s. in_def: %s, in_class: %s.\n", $cname, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + compstmt + keyword_end + %parser-state-pop(in_def) + %parser-state-pop(in_class) + { + printf("2. cname => %s. in_def: %s, in_class: %s.\n", $2, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + | keyword_def + %parser-state-push(in_def, in_def) + %parser-state-push(in_class, not_in_class) + fname + { + printf("1. fname => %s. in_def: %s, in_class: %s.\n", $2, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + compstmt + keyword_end + %parser-state-pop(in_def) + %parser-state-pop(in_class) + { + printf("2. fname => %s. in_def: %s, in_class: %s.\n", $fname, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + ; + +%% + +static int yyerror(YYLTYPE *loc, const char *str) { + fprintf(stderr, "parse error: %s\\n", str); + return 0; +} + +int main(int argc, char *argv[]) { + yydebug = 1; + + if (argc == 2) { + yy_scan_string(argv[1]); + } + + yyparse(); + return 0; +} diff --git a/spec/lrama/grammar/parser_state_spec.rb b/spec/lrama/grammar/parser_state_spec.rb new file mode 100644 index 00000000..59874aa4 --- /dev/null +++ b/spec/lrama/grammar/parser_state_spec.rb @@ -0,0 +1,177 @@ +RSpec.describe Lrama::Grammar::ParserState do + let(:location) { Lrama::Lexer::Location.new(first_line: 1, first_column: 0, last_line: 1, last_column: 0) } + let(:state_id) { Lrama::Lexer::Token::Ident.new(s_value: "in_rescue", location: location) } + let(:state_list) do + [ + Lrama::Lexer::Token::Ident.new(s_value: "before_rescue", location: location), + Lrama::Lexer::Token::Ident.new(s_value: "after_rescue", location: location), + Lrama::Lexer::Token::Ident.new(s_value: "after_else", location: location), + Lrama::Lexer::Token::Ident.new(s_value: "after_ensure", location: location) + ] + end + let(:parser_state) { Lrama::Grammar::ParserState.new(state_id: state_id, state_list: state_list) } + + describe "#enum_definition" do + it "returns enum definition" do + expect(parser_state.enum_definition).to eq <<~ENUM + enum yyparser_state_in_rescue + { + yyparser_state_before_rescue, + yyparser_state_after_rescue, + yyparser_state_after_else, + yyparser_state_after_ensure + }; + typedef enum yyparser_state_in_rescue yyparser_state_in_rescue_t; + + static const char *const yyparser_state_in_rescue_names[] = { + "before_rescue", "after_rescue", "after_else", "after_ensure", YY_NULLPTR + }; + + YY_ATTRIBUTE_UNUSED + static const char * + yyparser_state_in_rescue_name (yyparser_state_in_rescue_t num) + { + return yyparser_state_in_rescue_names[num]; + } + + # define YY_STATE_IN_RESCUE_NAME(value) yyparser_state_in_rescue_name (value) + # define YY_CURRENT_STATE_IN_RESCUE_NAME YY_STATE_IN_RESCUE_NAME (*yyparser_state_in_rescue_p) + ENUM + end + end + + describe "#state_name_macro" do + it "returns name of state name macro" do + expect(parser_state.state_name_macro).to eq "YY_STATE_IN_RESCUE_NAME" + end + end + + describe "#current_state_name_macro" do + it "returns name of current state name macro" do + expect(parser_state.current_state_name_macro).to eq "YY_CURRENT_STATE_IN_RESCUE_NAME" + end + end + + describe "#states_functions" do + it "returns states functions" do + expect(parser_state.states_functions).to eq <<~FUNC + # define YYPUSH_STATE_IN_RESCUE(value) \\ + do \\ + { \\ + if (yyparser_state_in_rescue_b + yyparser_state_in_rescue_stacksize - 1 <= yyparser_state_in_rescue_p) \\ + YYSTATE_STACK_INCREASE (yyparser_state_in_rescue_a, yyparser_state_in_rescue_b, yyparser_state_in_rescue_p, yyparser_state_in_rescue_stacksize, "in_rescue"); \\ + YYDPRINTF ((stderr, "Push %s to in_rescue\\n", YY_STATE_IN_RESCUE_NAME (yyparser_state_ ## value))); \\ + *++yyparser_state_in_rescue_p = yyparser_state_ ## value; \\ + } \\ + while (0) + + # define YYPOP_STATE_IN_RESCUE() \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Pop in_rescue\\n")); \\ + if (yyparser_state_in_rescue_p != yyparser_state_in_rescue_b) \\ + { \\ + yyparser_state_in_rescue_p -= 1; \\ + } \\ + else \\ + { \\ + YYDPRINTF ((stderr, "Try to pop empty in_rescue stack\\n")); \\ + } \\ + } \\ + while (0) + + # define YYSET_STATE_IN_RESCUE(value) \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Set %s to in_rescue\\n", YY_STATE_IN_RESCUE_NAME (yyparser_state_ ## value))); \\ + *yyparser_state_in_rescue_p = yyparser_state_ ## value; \\ + } \\ + while (0) + + # define YY_STATE_IN_RESCUE yyparser_state_in_rescue_p + FUNC + end + end + + describe "#states_clean_up_stack" do + it "returns states clean up codes" do + expect(parser_state.states_clean_up_stack).to eq <<~CODE + if (yyparser_state_in_rescue_b != yyparser_state_in_rescue_a) + YYSTACK_FREE (yyparser_state_in_rescue_b); + CODE + end + end + + describe "#states_stack_size_name" do + it "returns states stack size name" do + expect(parser_state.states_stack_size_name).to eq "yyparser_state_in_rescue_stacksize" + end + end + + describe "#states_stacks" do + it "returns states stacks" do + expect(parser_state.states_stacks).to eq <<~STACKS + /* Current size of state stack size */ + YYPTRDIFF_T yyparser_state_in_rescue_stacksize = YYINITDEPTH; + + /* The parser state stack (yyparser_state_in_rescue): array, bottom, top. */ + int yyparser_state_in_rescue_a[YYINITDEPTH]; + int *yyparser_state_in_rescue_b = yyparser_state_in_rescue_a; + int *yyparser_state_in_rescue_p = yyparser_state_in_rescue_b; + STACKS + end + end + + describe "#state_name" do + it "returns state name" do + expect(parser_state.state_name).to eq "in_rescue" + end + end + + describe "#enum_name" do + it "returns enum name" do + expect(parser_state.enum_name).to eq "yyparser_state_in_rescue" + end + end + + describe "#enum_type" do + it "returns enum type" do + expect(parser_state.enum_type).to eq "yyparser_state_in_rescue_t" + end + end + + describe "#enum_body" do + it "returns enum body" do + expect(parser_state.enum_body).to eq <<~BODY.chomp + yyparser_state_before_rescue, + yyparser_state_after_rescue, + yyparser_state_after_else, + yyparser_state_after_ensure + BODY + end + end + + describe "#int_to_name" do + it "returns int to name table" do + expect(parser_state.int_to_name).to eq [ + "\"before_rescue\"", + "\"after_rescue\"", + "\"after_else\"", + "\"after_ensure\"", + "YY_NULLPTR" + ] + end + end + + describe "#enum_name_table_name" do + it "returns table name" do + expect(parser_state.enum_name_table_name).to eq "yyparser_state_in_rescue_names" + end + end + + describe "#stack_prefix" do + it "returns prefix" do + expect(parser_state.stack_prefix).to eq "yyparser_state_in_rescue" + end + end +end diff --git a/spec/lrama/grammar/rule_builder_spec.rb b/spec/lrama/grammar/rule_builder_spec.rb index 2e48ac75..1b9c1c30 100644 --- a/spec/lrama/grammar/rule_builder_spec.rb +++ b/spec/lrama/grammar/rule_builder_spec.rb @@ -229,7 +229,7 @@ rule_builder.user_code = token_5 rule_builder.complete_input - expect { rule_builder.send(:preprocess_references) }.to raise_error(/Can not refer following component\. 10 >= 4\./) + expect { rule_builder.send(:preprocess_references) }.to raise_error(/Can not refer to not exist component\. \$10/) end end diff --git a/spec/lrama/integration_spec.rb b/spec/lrama/integration_spec.rb index 0669604a..1b7ca05d 100644 --- a/spec/lrama/integration_spec.rb +++ b/spec/lrama/integration_spec.rb @@ -9,7 +9,7 @@ def exec_command(command) raise "#{command} failed." unless $?.success? end - def test_parser(parser_name, input, expected, lrama_command_args: [], debug: false) + def test_parser(parser_name, input, expected, lrama_command_args: [], gcc_options: "", debug: false) tmpdir = Dir.tmpdir grammar_file_path = fixture_path("integration/#{parser_name}.y") lexer_file_path = fixture_path("integration/#{parser_name}.l") @@ -28,7 +28,7 @@ def test_parser(parser_name, input, expected, lrama_command_args: [], debug: fal Lrama::Command.new.run(%W[-H#{parser_h_path} -o#{parser_c_path}] + lrama_command_args + %W[#{grammar_file_path}]) exec_command("#{flex} --header-file=#{lexer_h_path} -o #{lexer_c_path} #{lexer_file_path}") - exec_command("gcc -Wall -ggdb3 -I#{tmpdir} #{parser_c_path} #{lexer_c_path} -o #{obj_path}") + exec_command("gcc -Wall -ggdb3 #{gcc_options} -I#{tmpdir} #{parser_c_path} #{lexer_c_path} -o #{obj_path}") out = err = status = nil @@ -153,6 +153,130 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: []) end end + describe "parser state" do + it "prints current 'in_rescue' state" do + input = <<~INPUT + def m1 + class A + class B + def m2 + end + end + end + end + INPUT + + expected = <<~OUTPUT + 0 => in_def: not_in_def, in_class: not_in_class. + 0 => before_rescue + 1. fname => m1. in_def: in_def, in_class: not_in_class. + 1. cname => A. in_def: not_in_def, in_class: in_class. + 1. cname => B. in_def: not_in_def, in_class: in_class. + 1. fname => m2. in_def: in_def, in_class: not_in_class. + 2. fname => m2. in_def: not_in_def, in_class: in_class. + 2. cname => B. in_def: not_in_def, in_class: in_class. + 2. cname => A. in_def: in_def, in_class: not_in_class. + 2. fname => m1. in_def: not_in_def, in_class: not_in_class. + 2 => before_rescue + 3 => before_rescue + 4 => before_rescue + 5 => before_rescue + 1 => before_rescue + OUTPUT + + test_parser("parser_state", input, expected) + test_parser("parser_state", input, expected, gcc_options: "-DYYINITDEPTH") + + + # See: https://github.com/ruby/ruby/commit/eaa0fbf9b956fa25e73c3d55e2eba8887324e233 + input = <<~INPUT + begin + 1 + rescue + 2 + else + 3 + ensure + 4 + end + INPUT + + expected = <<~OUTPUT + 0 => in_def: not_in_def, in_class: not_in_class. + 0 => before_rescue + NUM => 1 + 2 => before_rescue + 6 => after_rescue + NUM => 2 + 7 => before_rescue + 3 => before_rescue + NUM => 3 + 4 => after_else + NUM => 4 + 5 => after_ensure + 2 => after_ensure + 3 => after_ensure + 4 => after_ensure + 5 => after_ensure + 1 => after_ensure + OUTPUT + + test_parser("parser_state", input, expected) + + + input = <<~INPUT + begin + 1 + rescue + begin + 2 + rescue + 3 + else + 4 + ensure + 5 + end + else + 6 + ensure + 7 + end + INPUT + + expected = <<~OUTPUT + 0 => in_def: not_in_def, in_class: not_in_class. + 0 => before_rescue + NUM => 1 + 2 => before_rescue + 6 => after_rescue + NUM => 2 + 2 => after_rescue + 6 => after_rescue + NUM => 3 + 7 => after_rescue + 3 => after_rescue + NUM => 4 + 4 => after_else + NUM => 5 + 5 => after_ensure + 7 => before_rescue + 3 => before_rescue + NUM => 6 + 4 => after_else + NUM => 7 + 5 => after_ensure + 2 => after_ensure + 3 => after_ensure + 4 => after_ensure + 5 => after_ensure + 1 => after_ensure + OUTPUT + + test_parser("parser_state", input, expected) + end + end + describe "sample files" do let(:c_path) { Dir.tmpdir + "/test.c" } let(:obj_path) { Dir.tmpdir + "/test" } diff --git a/template/bison/yacc.c b/template/bison/yacc.c index f72d3461..b34a55a8 100644 --- a/template/bison/yacc.c +++ b/template/bison/yacc.c @@ -460,6 +460,9 @@ union yyalloc /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK <%= output.yymaxutok %> +<%- output.parser_states_enums.each do |enum| -%> +<%= enum %> +<%- end -%> /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM as returned by yylex, with out-of-bounds checking. */ @@ -1149,7 +1152,50 @@ yydestruct (const char *yymsg, YY_IGNORE_MAYBE_UNINITIALIZED_END } +/*------------------------. +| State stack functions. | +`------------------------*/ + +<%- if output.has_parser_states? -%> +#if !defined YYSTACK_RELOCATE +#define YYSTATE_STACK_INCREASE(stack_array, stack_bottom, stack_top, new_stack_size, name) \ + do \ + { \ + YYNOMEM; \ + } \ + while (0) +#else +#define YYSTATE_STACK_INCREASE(stack_array, stack_bottom, stack_top, stack_size, name) \ + do \ + { \ + { \ + YYPTRDIFF_T current_stack_size = stack_top - stack_bottom + 1; \ + if (YYMAXDEPTH <= stack_size) \ + YYNOMEM; \ + stack_size *= 2; \ + if (YYMAXDEPTH < stack_size) \ + stack_size = YYMAXDEPTH; \ + { \ + int *prev_bottom = stack_bottom; \ + int *new_stack = (int *) YYMALLOC (sizeof (int *) * stack_size); \ + if (!new_stack) \ + YYNOMEM; \ + YYCOPY (new_stack, stack_bottom, current_stack_size); \ + stack_bottom = new_stack; \ + stack_top = stack_bottom + current_stack_size - 1; \ + if (prev_bottom != stack_array) \ + YYSTACK_FREE (prev_bottom); \ + YYDPRINTF ((stderr, "State stack size increased to %ld (%s)\n", YY_CAST (long, current_stack_size), name)); \ + } \ + } \ + } \ + while (0) +#endif +<%- end -%> +<%- output.parser_states_functions.each do |func| -%> +<%= func %> +<%- end -%> <%- if output.error_recovery -%> #ifndef YYMAXREPAIR @@ -1511,6 +1557,10 @@ YYLTYPE yylloc = yyloc_default; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp = yyls; + <%- output.parser_states_stacks.each do |states_stacks| -%> + <%= states_stacks %> + <%- end -%> + int yyn; /* The return value of yyparse. */ int yyresult; @@ -2038,6 +2088,9 @@ YYLTYPE yylloc = yyloc_default; #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); +<%- output.parser_states_clean_up_stack.each do |clean_up| -%> +<%= clean_up %> +<%- end -%> #endif if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg);