From bcbfc229c4dbaaaf4487f5a5b8d7e147011671bc Mon Sep 17 00:00:00 2001 From: yui-knk Date: Tue, 24 Oct 2023 17:50:44 +0900 Subject: [PATCH] wip --- Steepfile | 4 + lib/lrama/grammar.rb | 10 +- lib/lrama/grammar/parser_state.rb | 123 +++ lib/lrama/grammar/rule_builder.rb | 20 + lib/lrama/lexer.rb | 4 + lib/lrama/lexer/token.rb | 3 + lib/lrama/lexer/token/parser_state_pop.rb | 8 + lib/lrama/lexer/token/parser_state_push.rb | 9 + lib/lrama/lexer/token/parser_state_set.rb | 9 + lib/lrama/output.rb | 18 + lib/lrama/parser.rb | 891 +++++++++++--------- parser.y | 33 + sig/lrama/grammar.rbs | 2 + sig/lrama/grammar/parser_state.rbs | 23 + sig/lrama/grammar/rule_builder.rbs | 1 + sig/lrama/lexer/token/parser_state_pop.rbs | 8 + sig/lrama/lexer/token/parser_state_push.rbs | 9 + sig/lrama/lexer/token/parser_state_set.rbs | 9 + spec/fixtures/integration/parser_state.l | 85 ++ spec/fixtures/integration/parser_state.y | 130 +++ spec/lrama/grammar/parser_state_spec.rb | 157 ++++ spec/lrama/integration_spec.rb | 117 ++- template/bison/yacc.c | 11 + 23 files changed, 1283 insertions(+), 401 deletions(-) create mode 100644 lib/lrama/grammar/parser_state.rb create mode 100644 lib/lrama/lexer/token/parser_state_pop.rb create mode 100644 lib/lrama/lexer/token/parser_state_push.rb create mode 100644 lib/lrama/lexer/token/parser_state_set.rb create mode 100644 sig/lrama/grammar/parser_state.rbs create mode 100644 sig/lrama/lexer/token/parser_state_pop.rbs create mode 100644 sig/lrama/lexer/token/parser_state_push.rbs create mode 100644 sig/lrama/lexer/token/parser_state_set.rbs create mode 100644 spec/fixtures/integration/parser_state.l create mode 100644 spec/fixtures/integration/parser_state.y create mode 100644 spec/lrama/grammar/parser_state_spec.rb diff --git a/Steepfile b/Steepfile index bdc40f48..f731326c 100644 --- a/Steepfile +++ b/Steepfile @@ -7,6 +7,7 @@ target :lib do check "lib/lrama/grammar/code/printer_code.rb" check "lib/lrama/grammar/code.rb" check "lib/lrama/grammar/counter.rb" + 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" @@ -15,6 +16,9 @@ target :lib do check "lib/lrama/lexer/token/char.rb" check "lib/lrama/lexer/token/ident.rb" check "lib/lrama/lexer/token/parameterizing.rb" + check "lib/lrama/lexer/token/parser_state_pop.rb" + check "lib/lrama/lexer/token/parser_state_push.rb" + check "lib/lrama/lexer/token/parser_state_set.rb" check "lib/lrama/lexer/token/tag.rb" check "lib/lrama/lexer/token/user_code.rb" check "lib/lrama/lexer/location.rb" diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index 9664caeb..9b65f54d 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" @@ -16,7 +17,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, @@ -31,6 +32,7 @@ def initialize(rule_counter) @percent_codes = [] @printers = [] @error_tokens = [] + @parser_states = [] @symbols = [] @types = [] @rule_builders = [] @@ -58,6 +60,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 @@ -186,7 +192,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..ea57f911 --- /dev/null +++ b/lib/lrama/grammar/parser_state.rb @@ -0,0 +1,123 @@ +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 + # TODO: Stack check for push + <<~FUNC + # define YYPUSH_STATE_#{state_name.upcase}(value) \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Push %s to #{state_name}\\n", #{state_name_macro} (value))); \\ + *++#{stack_prefix}_p = value; \\ + } \\ + while (0) + + # define YYPOP_STATE_#{state_name.upcase}() \\ + do \\ + { \\ + YYDPRINTF ((stderr, "Pop #{state_name}\\n")); \\ + if (#{stack_prefix}_p != #{stack_prefix}) \\ + { \\ + #{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} (value))); \\ + *#{stack_prefix}_p = value; \\ + } \\ + while (0) + + # define YY_STATE_#{state_name.upcase} #{stack_prefix}_p + FUNC + end + + def states_stacks + <<~STACKS + /* The parser state stack (#{stack_prefix}): array, bottom, top. */ + int #{stack_prefix}_a[YYINITDEPTH]; + int *#{stack_prefix} = #{stack_prefix}_a; + int *#{stack_prefix}_p = #{stack_prefix}; + 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 + state_list.map do |state| + state.s_value + end.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 + end + end +end diff --git a/lib/lrama/grammar/rule_builder.rb b/lib/lrama/grammar/rule_builder.rb index 80cd0c2c..b7749445 100644 --- a/lib/lrama/grammar/rule_builder.rb +++ b/lib/lrama/grammar/rule_builder.rb @@ -117,6 +117,12 @@ def process_rhs when Lrama::Lexer::Token::Parameterizing @parameterizing_rules = ParameterizingRules::Builder.new(token, @rule_counter, lhs, user_code, precedence_sym, line).build @replaced_rhs << token + when Lrama::Lexer::Token::ParserStatePop + process_parser_state_token(token, "parser_state_pop_", "YYPOP_STATE_#{token.s_value.upcase}();", i) + when Lrama::Lexer::Token::ParserStatePush + process_parser_state_token(token, "parser_state_push_", "YYPUSH_STATE_#{token.s_value.upcase}(#{token.state.s_value});", i) + when Lrama::Lexer::Token::ParserStateSet + process_parser_state_token(token, "parser_state_set_", "YYSET_STATE_#{token.s_value.upcase}(#{token.state.s_value});", i) when Lrama::Lexer::Token::UserCode prefix = token.referred ? "@" : "$@" new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s) @@ -135,6 +141,20 @@ def process_rhs end end + def process_parser_state_token(token, prefix, code, position_in_original_rule_rhs) + 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 + + @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| diff --git a/lib/lrama/lexer.rb b/lib/lrama/lexer.rb index 18d702a4..b64caf1f 100644 --- a/lib/lrama/lexer.rb +++ b/lib/lrama/lexer.rb @@ -28,6 +28,10 @@ class Lexer %error-token %empty %code + %parser-state + %push + %pop + %set ) def initialize(text) diff --git a/lib/lrama/lexer/token.rb b/lib/lrama/lexer/token.rb index 3b1b1f4f..c7b3c4ee 100644 --- a/lib/lrama/lexer/token.rb +++ b/lib/lrama/lexer/token.rb @@ -40,5 +40,8 @@ def last_column require 'lrama/lexer/token/char' require 'lrama/lexer/token/ident' require 'lrama/lexer/token/parameterizing' +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/output.rb b/lib/lrama/output.rb index f6720850..e4305f0d 100644 --- a/lib/lrama/output.rb +++ b/lib/lrama/output.rb @@ -358,6 +358,24 @@ def percent_code(name) end.join 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 + private def eval_template(file, path) diff --git a/lib/lrama/parser.rb b/lib/lrama/parser.rb index 8cad730f..909cbec4 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', 417) +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 450) include Lrama::Report::Duration @@ -749,256 +749,280 @@ def carrets(first_column, last_column) ##### State transition tables begin ### racc_action_table = [ - 82, 42, 83, 137, 38, 65, 42, 136, 137, 151, - 65, 169, 170, 152, 153, 154, 42, 139, 41, 135, - 3, 56, 139, 20, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 38, 6, 8, 7, 140, 77, 42, - 84, 41, 140, 65, 61, 42, 42, 41, 41, 32, - 68, 68, 20, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 9, 42, 39, 41, 12, 13, 14, 15, - 16, 17, 45, 45, 18, 19, 20, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 42, 42, 41, 41, - 45, 68, 68, 42, 42, 41, 41, 65, 163, 42, - 42, 41, 41, 65, 163, 42, 42, 41, 41, 65, - 163, 42, 42, 41, 41, 65, 163, 42, 42, 41, - 41, 65, 163, 42, 42, 41, 41, 65, 163, 42, - 42, 41, 41, 65, 65, 42, 42, 41, 41, 65, - 65, 42, 42, 41, 41, 65, 65, 42, 42, 41, - 41, 65, 65, 42, 42, 41, 41, 42, 42, 41, - 41, 48, 49, 50, 51, 52, 53, 74, 78, 80, - 85, 85, 85, 87, 93, 97, 98, 101, 101, 101, - 101, 106, 107, 109, 111, 112, 113, 114, 115, 118, - 121, 122, 125, 126, 127, 129, 142, 144, 145, 146, - 147, 148, 125, 80, 158, 159, 167, 173, 174, 80 ] + 84, 43, 85, 145, 39, 67, 187, 144, 43, 43, + 145, 42, 67, 6, 58, 7, 3, 147, 43, 143, + 42, 188, 67, 63, 147, 8, 21, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 33, 39, 148, 149, + 150, 151, 79, 40, 86, 148, 149, 150, 151, 163, + 43, 43, 42, 42, 46, 70, 70, 46, 46, 21, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 9, + 164, 165, 166, 12, 13, 14, 15, 16, 17, 49, + 50, 18, 19, 51, 52, 20, 21, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 43, 43, 42, 42, + 53, 70, 70, 43, 43, 42, 42, 67, 178, 43, + 43, 42, 42, 67, 178, 43, 43, 42, 42, 67, + 178, 43, 43, 42, 42, 67, 178, 43, 43, 42, + 42, 67, 178, 43, 43, 42, 42, 67, 178, 43, + 43, 42, 42, 67, 67, 43, 43, 42, 42, 67, + 67, 43, 43, 42, 42, 67, 67, 43, 43, 42, + 42, 67, 67, 43, 43, 42, 42, 43, 43, 42, + 42, 43, 54, 42, 55, 76, 80, 82, 87, 87, + 87, 89, 91, 96, 100, 101, 104, 104, 104, 104, + 109, 110, 112, 114, 117, 118, 119, 120, 121, 124, + 127, 128, 131, 132, 133, 135, 137, 138, 153, 155, + 156, 157, 158, 159, 160, 131, 82, 170, 171, 172, + 173, 174, 182, 183, 184, 185, 190, 191, 192, 194, + 195, 196, 197, 82, 199, 200 ] racc_action_check = [ - 40, 124, 40, 124, 9, 124, 149, 123, 149, 137, - 149, 166, 166, 137, 137, 137, 25, 124, 25, 123, - 1, 25, 149, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 33, 2, 3, 2, 124, 33, 26, - 40, 26, 149, 26, 26, 27, 28, 27, 28, 7, - 27, 28, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 4, 13, 12, 13, 4, 4, 4, 4, - 4, 4, 14, 15, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 29, 30, 29, 30, - 16, 29, 30, 146, 55, 146, 55, 146, 146, 147, - 56, 147, 56, 147, 147, 148, 67, 148, 67, 148, - 148, 160, 68, 160, 68, 160, 160, 164, 93, 164, - 93, 164, 164, 165, 95, 165, 95, 165, 165, 60, - 61, 60, 61, 60, 61, 98, 100, 98, 100, 98, - 100, 119, 140, 119, 140, 119, 140, 151, 170, 151, - 170, 151, 170, 101, 103, 101, 103, 116, 120, 116, - 120, 17, 18, 20, 22, 23, 24, 31, 36, 37, - 44, 46, 47, 48, 54, 58, 59, 66, 71, 72, - 73, 79, 80, 86, 88, 89, 90, 91, 92, 96, - 104, 105, 106, 107, 108, 110, 128, 130, 131, 132, - 133, 134, 135, 138, 141, 143, 156, 171, 172, 173 ] + 41, 130, 41, 130, 9, 130, 181, 129, 161, 26, + 161, 26, 161, 2, 26, 2, 1, 130, 27, 129, + 27, 181, 27, 27, 161, 3, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 7, 34, 130, 130, + 130, 130, 34, 12, 41, 161, 161, 161, 161, 145, + 28, 29, 28, 29, 14, 28, 29, 15, 16, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 4, + 145, 145, 145, 4, 4, 4, 4, 4, 4, 17, + 18, 4, 4, 19, 21, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 30, 31, 30, 31, + 23, 30, 31, 158, 13, 158, 13, 158, 158, 159, + 57, 159, 57, 159, 159, 160, 58, 160, 58, 160, + 160, 175, 69, 175, 69, 175, 175, 179, 70, 179, + 70, 179, 179, 180, 96, 180, 96, 180, 180, 62, + 63, 62, 63, 62, 63, 101, 103, 101, 103, 101, + 103, 125, 148, 125, 148, 125, 148, 163, 188, 163, + 188, 163, 188, 98, 104, 98, 104, 106, 122, 106, + 122, 126, 24, 126, 25, 32, 37, 38, 45, 47, + 48, 49, 51, 56, 60, 61, 68, 73, 74, 75, + 81, 82, 88, 90, 91, 92, 93, 94, 95, 99, + 107, 108, 109, 110, 111, 113, 115, 116, 134, 136, + 138, 139, 140, 141, 142, 143, 146, 149, 150, 151, + 152, 154, 168, 170, 171, 172, 183, 184, 185, 189, + 190, 192, 193, 194, 195, 196 ] racc_action_pointer = [ - nil, 20, 24, 35, 53, nil, nil, 42, nil, 0, - nil, nil, 58, 60, 53, 54, 71, 156, 143, nil, - 144, nil, 145, 146, 147, 13, 36, 42, 43, 83, - 84, 165, nil, 29, nil, nil, 146, 126, nil, nil, - -5, nil, nil, nil, 151, nil, 152, 153, 154, nil, - nil, nil, nil, nil, 166, 91, 97, nil, 169, 168, - 126, 127, nil, nil, nil, nil, 169, 103, 109, nil, - nil, 170, 171, 172, nil, nil, nil, nil, nil, 148, - 177, nil, nil, nil, nil, nil, 181, nil, 182, 183, - 184, 185, 186, 115, nil, 121, 182, nil, 132, nil, - 133, 150, nil, 151, 179, 189, 157, 149, 192, nil, - 193, nil, nil, nil, nil, nil, 154, nil, nil, 138, - 155, nil, nil, -15, -2, nil, nil, nil, 176, nil, - 177, 178, 179, 180, 181, 167, nil, -27, 160, nil, - 139, 184, nil, 185, nil, nil, 90, 96, 102, 3, - nil, 144, nil, nil, nil, nil, 204, nil, nil, nil, - 108, nil, nil, nil, 114, 120, -26, nil, nil, nil, - 145, 187, 171, 166, nil, nil ] + nil, 16, 3, 25, 60, nil, nil, 29, nil, 0, + nil, nil, 37, 101, 35, 38, 39, 74, 61, 78, + nil, 65, nil, 81, 153, 155, 6, 15, 47, 48, + 93, 94, 173, nil, 33, nil, nil, 151, 130, nil, + nil, -5, nil, nil, nil, 159, nil, 160, 161, 162, + nil, 159, nil, nil, nil, nil, 175, 107, 113, nil, + 178, 177, 136, 137, nil, nil, nil, nil, 178, 119, + 125, nil, nil, 179, 180, 181, nil, nil, nil, nil, + nil, 154, 186, nil, nil, nil, nil, nil, 190, nil, + 191, 189, 193, 194, 195, 196, 131, nil, 160, 192, + nil, 142, nil, 143, 161, nil, 164, 189, 199, 164, + 155, 202, nil, 203, nil, 182, 168, nil, nil, nil, + nil, nil, 165, nil, nil, 148, 168, nil, nil, -18, + -2, nil, nil, nil, 188, nil, 189, nil, 205, 191, + 192, 193, 194, 177, nil, 26, 169, nil, 149, 194, + 195, 196, 200, nil, 201, nil, nil, nil, 100, 106, + 112, 5, nil, 154, nil, nil, nil, nil, 220, nil, + 218, 219, 220, nil, nil, 118, nil, nil, nil, 124, + 130, -18, nil, 187, 203, 189, nil, nil, 155, 209, + 225, nil, 226, 208, 186, 210, 211, nil, nil, nil, + nil ] racc_action_default = [ - -2, -110, -8, -110, -110, -3, -4, -110, 176, -110, - -9, -10, -110, -110, -110, -110, -110, -110, -110, -22, - -110, -26, -110, -110, -110, -110, -110, -110, -110, -110, - -110, -110, -7, -97, -73, -75, -110, -94, -96, -11, - -101, -71, -72, -100, -13, -62, -14, -15, -110, -19, - -23, -27, -30, -33, -36, -42, -110, -45, -48, -37, - -52, -110, -55, -57, -58, -109, -38, -65, -110, -68, - -70, -39, -40, -41, -5, -1, -74, -98, -76, -110, - -110, -12, -102, -103, -104, -59, -110, -16, -110, -110, - -110, -110, -110, -110, -46, -43, -50, -49, -110, -56, - -53, -110, -69, -66, -110, -110, -81, -110, -110, -63, - -110, -20, -24, -28, -31, -34, -44, -47, -51, -54, - -67, -6, -99, -77, -78, -82, -95, -60, -110, -17, - -110, -110, -110, -110, -110, -81, -80, -71, -94, -87, - -110, -110, -64, -110, -21, -25, -110, -110, -110, -79, - -84, -110, -91, -92, -93, -83, -110, -90, -61, -18, - -29, -105, -107, -108, -32, -35, -110, -88, -106, -85, - -110, -110, -110, -94, -86, -89 ] + -2, -118, -8, -118, -118, -3, -4, -118, 201, -118, + -9, -10, -118, -118, -118, -118, -118, -118, -118, -118, + -23, -118, -27, -118, -118, -118, -118, -118, -118, -118, + -118, -118, -118, -7, -101, -74, -76, -118, -98, -100, + -11, -105, -72, -73, -104, -13, -63, -14, -15, -118, + -19, -118, -24, -28, -31, -34, -37, -43, -118, -46, + -49, -38, -53, -118, -56, -58, -59, -117, -39, -66, + -118, -69, -71, -40, -41, -42, -5, -1, -75, -102, + -77, -118, -118, -12, -106, -107, -108, -60, -118, -16, + -118, -113, -118, -118, -118, -118, -118, -47, -44, -51, + -50, -118, -57, -54, -118, -70, -67, -118, -118, -82, + -118, -118, -64, -118, -20, -118, -114, -115, -25, -29, + -32, -35, -45, -48, -52, -55, -68, -6, -103, -78, + -79, -83, -99, -61, -118, -17, -118, -22, -118, -118, + -118, -118, -118, -82, -81, -72, -98, -88, -118, -118, + -118, -118, -118, -65, -118, -21, -116, -26, -118, -118, + -118, -80, -85, -118, -95, -96, -97, -84, -118, -91, + -118, -118, -118, -62, -18, -30, -109, -111, -112, -33, + -36, -118, -89, -118, -118, -118, -110, -86, -118, -118, + -118, -93, -118, -118, -98, -118, -118, -87, -90, -92, + -94 ] racc_goto_table = [ - 62, 79, 43, 60, 103, 55, 94, 102, 34, 1, - 124, 44, 46, 47, 58, 2, 70, 70, 70, 70, - 168, 160, 164, 165, 168, 168, 66, 71, 72, 73, - 4, 33, 76, 75, 99, 62, 95, 120, 100, 149, - 5, 31, 104, 102, 58, 58, 94, 10, 11, 40, - 81, 110, 143, 88, 130, 89, 70, 70, 131, 90, - 102, 132, 91, 133, 92, 134, 54, 94, 59, 96, - 117, 108, 62, 116, 99, 119, 141, 86, 128, 123, - 150, 156, 58, 171, 58, 105, nil, nil, nil, nil, - 70, nil, 70, 99, nil, nil, nil, nil, 138, nil, - nil, nil, 155, nil, nil, 58, nil, nil, nil, 70, - nil, nil, nil, nil, 157, nil, nil, nil, nil, nil, - nil, nil, nil, 138, nil, 166, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 175, nil, nil, - nil, nil, nil, nil, 172 ] + 64, 81, 44, 62, 97, 57, 105, 106, 130, 35, + 68, 73, 74, 75, 1, 60, 2, 72, 72, 72, + 72, 186, 45, 47, 48, 186, 186, 175, 179, 180, + 4, 34, 77, 5, 78, 102, 64, 98, 32, 103, + 107, 126, 161, 105, 10, 97, 60, 60, 11, 41, + 83, 115, 113, 154, 90, 136, 92, 139, 72, 72, + 93, 140, 94, 105, 141, 95, 142, 56, 61, 97, + 99, 123, 111, 152, 64, 122, 102, 125, 88, 134, + 129, 162, 168, 189, 108, 60, 116, 60, nil, nil, + nil, nil, nil, 72, nil, 72, nil, nil, 102, nil, + nil, nil, nil, 146, nil, nil, nil, nil, nil, 167, + nil, 60, nil, nil, nil, 72, nil, nil, nil, nil, + nil, 169, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, 146, nil, 181, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 198, nil, nil, + nil, 193 ] racc_goto_check = [ - 37, 48, 33, 36, 43, 31, 32, 44, 45, 1, - 50, 13, 13, 13, 33, 2, 33, 33, 33, 33, - 55, 19, 19, 19, 55, 55, 30, 30, 30, 30, - 3, 4, 45, 5, 37, 37, 31, 43, 36, 50, - 6, 7, 8, 44, 33, 33, 32, 9, 10, 11, - 12, 14, 15, 16, 17, 20, 33, 33, 21, 22, - 44, 23, 24, 25, 26, 27, 28, 32, 29, 34, - 35, 39, 37, 31, 37, 36, 40, 41, 42, 49, - 51, 52, 33, 53, 33, 54, nil, nil, nil, nil, - 33, nil, 33, 37, nil, nil, nil, nil, 37, nil, - nil, nil, 48, nil, nil, 33, nil, nil, nil, 33, - nil, nil, nil, nil, 37, nil, nil, nil, nil, nil, - nil, nil, nil, 37, nil, 37, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 48, nil, nil, - nil, nil, nil, nil, 37 ] + 38, 49, 34, 37, 33, 32, 45, 44, 51, 46, + 31, 31, 31, 31, 1, 34, 2, 34, 34, 34, + 34, 56, 13, 13, 13, 56, 56, 20, 20, 20, + 3, 4, 5, 6, 46, 38, 38, 32, 7, 37, + 8, 44, 51, 45, 9, 33, 34, 34, 10, 11, + 12, 14, 15, 16, 17, 18, 21, 22, 34, 34, + 23, 24, 25, 45, 26, 27, 28, 29, 30, 33, + 35, 36, 40, 41, 38, 32, 38, 37, 42, 43, + 50, 52, 53, 54, 55, 34, 57, 34, nil, nil, + nil, nil, nil, 34, nil, 34, nil, nil, 38, nil, + nil, nil, nil, 38, nil, nil, nil, nil, nil, 49, + nil, 34, nil, nil, nil, 34, nil, nil, nil, nil, + nil, 38, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, 38, nil, 38, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 49, nil, nil, + nil, 38 ] racc_goto_pointer = [ - nil, 9, 15, 28, 22, 0, 38, 35, -32, 43, - 44, 36, 10, -3, -36, -77, 4, -57, nil, -125, - 5, -54, 8, -52, 10, -51, 11, -50, 41, 42, - -1, -20, -49, -11, 11, -26, -23, -26, nil, -14, - -51, 32, -31, -64, -60, -1, nil, nil, -36, -27, - -96, -57, -58, -84, 8, -140 ] + nil, 14, 16, 28, 22, -2, 31, 32, -36, 40, + 44, 36, 9, 8, -40, -37, -82, 4, -59, nil, + -131, 4, -61, 7, -58, 8, -56, 10, -55, 41, + 41, -18, -21, -53, -11, 10, -28, -24, -27, nil, + -15, -60, 32, -33, -63, -63, 0, nil, nil, -37, + -29, -101, -64, -65, -99, 5, -154, -5 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 36, nil, nil, nil, nil, nil, nil, nil, 21, nil, + 37, nil, nil, nil, nil, nil, nil, nil, nil, 22, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 57, 63, nil, nil, nil, 162, 64, nil, - nil, nil, nil, 67, 69, nil, 35, 37, nil, nil, - nil, nil, nil, nil, nil, 161 ] + nil, nil, nil, 59, 65, nil, nil, nil, 177, 66, + nil, nil, nil, nil, 69, 71, nil, 36, 38, nil, + nil, nil, nil, nil, nil, nil, 176, nil ] racc_reduce_table = [ 0, 0, :racc_error, - 5, 47, :_reduce_none, - 0, 48, :_reduce_none, - 2, 48, :_reduce_none, - 0, 53, :_reduce_4, - 0, 54, :_reduce_5, - 5, 52, :_reduce_6, + 5, 51, :_reduce_none, + 0, 52, :_reduce_none, 2, 52, :_reduce_none, - 0, 49, :_reduce_8, - 2, 49, :_reduce_none, - 1, 55, :_reduce_none, - 2, 55, :_reduce_11, - 3, 55, :_reduce_none, - 2, 55, :_reduce_none, - 2, 55, :_reduce_14, - 2, 55, :_reduce_15, - 0, 60, :_reduce_16, - 0, 61, :_reduce_17, - 7, 55, :_reduce_18, - 0, 62, :_reduce_19, - 0, 63, :_reduce_20, - 6, 55, :_reduce_21, - 1, 55, :_reduce_none, - 0, 66, :_reduce_23, - 0, 67, :_reduce_24, - 6, 56, :_reduce_25, - 1, 56, :_reduce_none, - 0, 68, :_reduce_27, - 0, 69, :_reduce_28, - 7, 56, :_reduce_none, - 0, 70, :_reduce_30, - 0, 71, :_reduce_31, - 7, 56, :_reduce_32, - 0, 72, :_reduce_33, - 0, 73, :_reduce_34, - 7, 56, :_reduce_35, - 2, 64, :_reduce_none, - 2, 64, :_reduce_37, - 2, 64, :_reduce_38, - 2, 64, :_reduce_39, - 2, 64, :_reduce_40, - 2, 64, :_reduce_41, - 1, 74, :_reduce_42, - 2, 74, :_reduce_43, - 3, 74, :_reduce_44, - 1, 77, :_reduce_45, - 2, 77, :_reduce_46, - 3, 78, :_reduce_47, - 0, 80, :_reduce_none, - 1, 80, :_reduce_none, - 0, 81, :_reduce_none, - 1, 81, :_reduce_none, - 1, 75, :_reduce_52, - 2, 75, :_reduce_53, - 3, 75, :_reduce_54, - 1, 82, :_reduce_55, - 2, 82, :_reduce_56, - 1, 83, :_reduce_none, - 1, 83, :_reduce_none, - 0, 85, :_reduce_59, - 0, 86, :_reduce_60, - 6, 59, :_reduce_61, - 0, 87, :_reduce_62, - 0, 88, :_reduce_63, - 5, 59, :_reduce_64, - 1, 76, :_reduce_65, - 2, 76, :_reduce_66, - 3, 76, :_reduce_67, - 1, 89, :_reduce_68, - 2, 89, :_reduce_69, - 1, 90, :_reduce_none, - 1, 79, :_reduce_71, - 1, 79, :_reduce_72, - 1, 50, :_reduce_none, - 2, 50, :_reduce_none, - 1, 91, :_reduce_none, - 2, 91, :_reduce_none, - 4, 92, :_reduce_77, - 1, 95, :_reduce_78, - 3, 95, :_reduce_79, - 2, 95, :_reduce_none, - 0, 96, :_reduce_81, - 1, 96, :_reduce_82, - 3, 96, :_reduce_83, - 3, 96, :_reduce_84, - 5, 96, :_reduce_85, - 7, 96, :_reduce_86, - 0, 98, :_reduce_87, - 0, 99, :_reduce_88, - 7, 96, :_reduce_89, - 3, 96, :_reduce_90, - 1, 97, :_reduce_none, - 1, 97, :_reduce_none, - 1, 97, :_reduce_none, - 0, 94, :_reduce_none, - 3, 94, :_reduce_95, - 1, 93, :_reduce_none, - 0, 51, :_reduce_none, - 0, 100, :_reduce_98, - 3, 51, :_reduce_99, - 1, 57, :_reduce_none, - 0, 58, :_reduce_none, - 1, 58, :_reduce_none, - 1, 58, :_reduce_none, - 1, 58, :_reduce_none, - 1, 65, :_reduce_105, - 2, 65, :_reduce_106, - 1, 101, :_reduce_none, - 1, 101, :_reduce_none, - 1, 84, :_reduce_109 ] - -racc_reduce_n = 110 - -racc_shift_n = 176 + 0, 57, :_reduce_4, + 0, 58, :_reduce_5, + 5, 56, :_reduce_6, + 2, 56, :_reduce_none, + 0, 53, :_reduce_8, + 2, 53, :_reduce_none, + 1, 59, :_reduce_none, + 2, 59, :_reduce_11, + 3, 59, :_reduce_none, + 2, 59, :_reduce_none, + 2, 59, :_reduce_14, + 2, 59, :_reduce_15, + 0, 65, :_reduce_16, + 0, 66, :_reduce_17, + 7, 59, :_reduce_18, + 0, 67, :_reduce_19, + 0, 68, :_reduce_20, + 6, 59, :_reduce_21, + 5, 59, :_reduce_22, + 1, 59, :_reduce_none, + 0, 71, :_reduce_24, + 0, 72, :_reduce_25, + 6, 60, :_reduce_26, + 1, 60, :_reduce_none, + 0, 73, :_reduce_28, + 0, 74, :_reduce_29, + 7, 60, :_reduce_none, + 0, 75, :_reduce_31, + 0, 76, :_reduce_32, + 7, 60, :_reduce_33, + 0, 77, :_reduce_34, + 0, 78, :_reduce_35, + 7, 60, :_reduce_36, + 2, 69, :_reduce_none, + 2, 69, :_reduce_38, + 2, 69, :_reduce_39, + 2, 69, :_reduce_40, + 2, 69, :_reduce_41, + 2, 69, :_reduce_42, + 1, 79, :_reduce_43, + 2, 79, :_reduce_44, + 3, 79, :_reduce_45, + 1, 82, :_reduce_46, + 2, 82, :_reduce_47, + 3, 83, :_reduce_48, + 0, 85, :_reduce_none, + 1, 85, :_reduce_none, + 0, 86, :_reduce_none, + 1, 86, :_reduce_none, + 1, 80, :_reduce_53, + 2, 80, :_reduce_54, + 3, 80, :_reduce_55, + 1, 87, :_reduce_56, + 2, 87, :_reduce_57, + 1, 88, :_reduce_none, + 1, 88, :_reduce_none, + 0, 90, :_reduce_60, + 0, 91, :_reduce_61, + 6, 63, :_reduce_62, + 0, 92, :_reduce_63, + 0, 93, :_reduce_64, + 5, 63, :_reduce_65, + 1, 81, :_reduce_66, + 2, 81, :_reduce_67, + 3, 81, :_reduce_68, + 1, 94, :_reduce_69, + 2, 94, :_reduce_70, + 1, 95, :_reduce_none, + 1, 84, :_reduce_72, + 1, 84, :_reduce_73, + 1, 54, :_reduce_none, + 2, 54, :_reduce_none, + 1, 96, :_reduce_none, + 2, 96, :_reduce_none, + 4, 97, :_reduce_78, + 1, 100, :_reduce_79, + 3, 100, :_reduce_80, + 2, 100, :_reduce_none, + 0, 101, :_reduce_82, + 1, 101, :_reduce_83, + 3, 101, :_reduce_84, + 3, 101, :_reduce_85, + 5, 101, :_reduce_86, + 7, 101, :_reduce_87, + 0, 103, :_reduce_88, + 0, 104, :_reduce_89, + 7, 101, :_reduce_90, + 3, 101, :_reduce_91, + 7, 101, :_reduce_92, + 5, 101, :_reduce_93, + 7, 101, :_reduce_94, + 1, 102, :_reduce_none, + 1, 102, :_reduce_none, + 1, 102, :_reduce_none, + 0, 99, :_reduce_none, + 3, 99, :_reduce_99, + 1, 98, :_reduce_none, + 0, 55, :_reduce_none, + 0, 105, :_reduce_102, + 3, 55, :_reduce_103, + 1, 61, :_reduce_none, + 0, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 70, :_reduce_109, + 2, 70, :_reduce_110, + 1, 106, :_reduce_none, + 1, 106, :_reduce_none, + 0, 64, :_reduce_none, + 1, 64, :_reduce_none, + 1, 107, :_reduce_115, + 3, 107, :_reduce_116, + 1, 89, :_reduce_117 ] + +racc_reduce_n = 118 + +racc_shift_n = 201 racc_token_table = { false => 0, @@ -1023,32 +1047,36 @@ def carrets(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, - ":" => 33, - "|" => 34, - "%empty" => 35, - "(" => 36, - ")" => 37, - "," => 38, - "%prec" => 39, - "?" => 40, - "+" => 41, - "*" => 42, - "[" => 43, - "]" => 44, - "{...}" => 45 } - -racc_nt_base = 46 + "%parser-state" => 22, + "(" => 23, + ")" => 24, + ";" => 25, + "%union" => 26, + "%destructor" => 27, + "%printer" => 28, + "%error-token" => 29, + "%token" => 30, + "%type" => 31, + "%left" => 32, + "%right" => 33, + "%precedence" => 34, + "%nonassoc" => 35, + ":" => 36, + "|" => 37, + "%empty" => 38, + "," => 39, + "%prec" => 40, + "%push" => 41, + "%pop" => 42, + "%set" => 43, + "?" => 44, + "+" => 45, + "*" => 46, + "[" => 47, + "]" => 48, + "{...}" => 49 } + +racc_nt_base = 50 racc_use_result_var = true @@ -1092,6 +1120,9 @@ def carrets(first_column, last_column) "\"{\"", "\"}\"", "\"%initial-action\"", + "\"%parser-state\"", + "\"(\"", + "\")\"", "\";\"", "\"%union\"", "\"%destructor\"", @@ -1106,10 +1137,11 @@ def carrets(first_column, last_column) "\":\"", "\"|\"", "\"%empty\"", - "\"(\"", - "\")\"", "\",\"", "\"%prec\"", + "\"%push\"", + "\"%pop\"", + "\"%set\"", "\"?\"", "\"+\"", "\"*\"", @@ -1130,6 +1162,7 @@ def carrets(first_column, last_column) "variable", "value", "params", + "identifier_list_opt", "@3", "@4", "@5", @@ -1171,7 +1204,8 @@ def carrets(first_column, last_column) "@19", "@20", "@21", - "generic_symlist_item" ] + "generic_symlist_item", + "identifier_list" ] Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor) Racc_debug_parser = true @@ -1303,19 +1337,19 @@ def _reduce_21(val, _values, result) end .,., -# reduce 22 omitted - -module_eval(<<'.,.,', 'parser.y', 74) - def _reduce_23(val, _values, result) - begin_c_declaration("}") +module_eval(<<'.,.,', 'parser.y', 72) + def _reduce_22(val, _values, result) + @grammar.add_parser_state(val[1], val[3]) result end .,., +# reduce 23 omitted + module_eval(<<'.,.,', 'parser.y', 78) def _reduce_24(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1323,6 +1357,14 @@ def _reduce_24(val, _values, result) module_eval(<<'.,.,', 'parser.y', 82) def _reduce_25(val, _values, result) + end_c_declaration + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 86) + def _reduce_26(val, _values, result) @grammar.set_union( Grammar::Code::NoReferenceCode.new(type: :union, token_code: val[3]), val[3].line @@ -1332,44 +1374,44 @@ def _reduce_25(val, _values, result) end .,., -# reduce 26 omitted +# reduce 27 omitted -module_eval(<<'.,.,', 'parser.y', 90) - def _reduce_27(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 94) + def _reduce_28(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 94) - def _reduce_28(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 98) + def _reduce_29(val, _values, result) end_c_declaration result end .,., -# reduce 29 omitted +# reduce 30 omitted -module_eval(<<'.,.,', 'parser.y', 99) - def _reduce_30(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 103) + def _reduce_31(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 103) - def _reduce_31(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 107) + def _reduce_32(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 107) - def _reduce_32(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 111) + def _reduce_33(val, _values, result) @grammar.add_printer( ident_or_tags: val[6], token_code: val[3], @@ -1380,24 +1422,24 @@ def _reduce_32(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 115) - def _reduce_33(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 119) + def _reduce_34(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 119) - def _reduce_34(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 123) + def _reduce_35(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 123) - def _reduce_35(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 127) + def _reduce_36(val, _values, result) @grammar.add_error_token( ident_or_tags: val[6], token_code: val[3], @@ -1408,10 +1450,10 @@ def _reduce_35(val, _values, result) end .,., -# reduce 36 omitted +# reduce 37 omitted -module_eval(<<'.,.,', 'parser.y', 133) - def _reduce_37(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 137) + def _reduce_38(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| @grammar.add_type(id: id, tag: hash[:tag]) @@ -1422,8 +1464,8 @@ def _reduce_37(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 141) - def _reduce_38(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 145) + def _reduce_39(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1436,8 +1478,8 @@ def _reduce_38(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 151) - def _reduce_39(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 155) + def _reduce_40(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1450,8 +1492,8 @@ def _reduce_39(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 161) - def _reduce_40(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 165) + def _reduce_41(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1464,8 +1506,8 @@ def _reduce_40(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 171) - def _reduce_41(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 175) + def _reduce_42(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1478,8 +1520,8 @@ def _reduce_41(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 182) - def _reduce_42(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 186) + def _reduce_43(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) } @@ -1488,8 +1530,8 @@ def _reduce_42(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 188) - def _reduce_43(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 192) + def _reduce_44(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) } @@ -1498,8 +1540,8 @@ def _reduce_43(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 194) - def _reduce_44(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 198) + def _reduce_45(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) } @@ -1508,88 +1550,80 @@ def _reduce_44(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 199) - def _reduce_45(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 203) + def _reduce_46(val, _values, result) result = [val[0]] 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].append(val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 202) - def _reduce_47(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 206) + def _reduce_48(val, _values, result) result = val result end .,., -# reduce 48 omitted - # reduce 49 omitted # reduce 50 omitted # reduce 51 omitted -module_eval(<<'.,.,', 'parser.y', 212) - def _reduce_52(val, _values, result) +# reduce 52 omitted + +module_eval(<<'.,.,', 'parser.y', 216) + def _reduce_53(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 216) - def _reduce_53(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 220) + def _reduce_54(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 220) - def _reduce_54(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 224) + def _reduce_55(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 223) - def _reduce_55(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 227) + def _reduce_56(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 224) - def _reduce_56(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 228) + def _reduce_57(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 57 omitted - # reduce 58 omitted -module_eval(<<'.,.,', 'parser.y', 231) - def _reduce_59(val, _values, result) - begin_c_declaration("}") - - result - end -.,., +# reduce 59 omitted module_eval(<<'.,.,', 'parser.y', 235) def _reduce_60(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1597,7 +1631,7 @@ def _reduce_60(val, _values, result) module_eval(<<'.,.,', 'parser.y', 239) def _reduce_61(val, _values, result) - result = val[0].append(val[3]) + end_c_declaration result end @@ -1605,7 +1639,7 @@ def _reduce_61(val, _values, result) module_eval(<<'.,.,', 'parser.y', 243) def _reduce_62(val, _values, result) - begin_c_declaration("}") + result = val[0].append(val[3]) result end @@ -1613,7 +1647,7 @@ def _reduce_62(val, _values, result) module_eval(<<'.,.,', 'parser.y', 247) def _reduce_63(val, _values, result) - end_c_declaration + begin_c_declaration("}") result end @@ -1621,15 +1655,15 @@ def _reduce_63(val, _values, result) module_eval(<<'.,.,', 'parser.y', 251) def _reduce_64(val, _values, result) - result = [val[2]] + end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 256) +module_eval(<<'.,.,', 'parser.y', 255) def _reduce_65(val, _values, result) - result = [{tag: nil, tokens: val[0]}] + result = [val[2]] result end @@ -1637,7 +1671,7 @@ def _reduce_65(val, _values, result) module_eval(<<'.,.,', 'parser.y', 260) def _reduce_66(val, _values, result) - result = [{tag: val[0], tokens: val[1]}] + result = [{tag: nil, tokens: val[0]}] result end @@ -1645,52 +1679,60 @@ def _reduce_66(val, _values, result) module_eval(<<'.,.,', 'parser.y', 264) def _reduce_67(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', 267) +module_eval(<<'.,.,', 'parser.y', 268) def _reduce_68(val, _values, result) - result = [val[0]] + result = val[0].append({tag: val[1], tokens: val[2]}) + result end .,., -module_eval(<<'.,.,', 'parser.y', 268) +module_eval(<<'.,.,', 'parser.y', 271) def _reduce_69(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 272) + def _reduce_70(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 70 omitted +# reduce 71 omitted -module_eval(<<'.,.,', 'parser.y', 272) - def _reduce_71(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 276) + def _reduce_72(val, _values, result) on_action_error("ident after %prec", val[0]) if @prec_seen result end .,., -module_eval(<<'.,.,', 'parser.y', 273) - def _reduce_72(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 277) + def _reduce_73(val, _values, result) on_action_error("char after %prec", val[0]) if @prec_seen result end .,., -# reduce 73 omitted - # reduce 74 omitted # reduce 75 omitted # reduce 76 omitted -module_eval(<<'.,.,', 'parser.y', 283) - def _reduce_77(val, _values, result) +# reduce 77 omitted + +module_eval(<<'.,.,', 'parser.y', 287) + def _reduce_78(val, _values, result) lhs = val[0] lhs.alias_name = val[1] val[3].each do |builder| @@ -1703,8 +1745,8 @@ def _reduce_77(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 294) - def _reduce_78(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 298) + def _reduce_79(val, _values, result) builder = val[0] if !builder.line builder.line = @lexer.line - 1 @@ -1715,8 +1757,8 @@ def _reduce_78(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 302) - def _reduce_79(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 306) + def _reduce_80(val, _values, result) builder = val[2] if !builder.line builder.line = @lexer.line - 1 @@ -1727,10 +1769,10 @@ def _reduce_79(val, _values, result) end .,., -# reduce 80 omitted +# reduce 81 omitted -module_eval(<<'.,.,', 'parser.y', 312) - def _reduce_81(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 316) + def _reduce_82(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1738,8 +1780,8 @@ def _reduce_81(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 317) - def _reduce_82(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 321) + def _reduce_83(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1747,8 +1789,8 @@ def _reduce_82(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 322) - def _reduce_83(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 326) + def _reduce_84(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1759,8 +1801,8 @@ def _reduce_83(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 330) - def _reduce_84(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 334) + def _reduce_85(val, _values, result) token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[2], location: @lexer.location, args: [val[1]]) builder = val[0] builder.add_rhs(token) @@ -1770,8 +1812,8 @@ def _reduce_84(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 337) - def _reduce_85(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 341) + def _reduce_86(val, _values, result) token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[1].s_value, location: @lexer.location, args: [val[3]]) builder = val[0] builder.add_rhs(token) @@ -1781,8 +1823,8 @@ def _reduce_85(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 344) - def _reduce_86(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 348) + def _reduce_87(val, _values, result) token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[1].s_value, location: @lexer.location, args: [val[3], val[5]]) builder = val[0] builder.add_rhs(token) @@ -1792,8 +1834,8 @@ def _reduce_86(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 351) - def _reduce_87(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 355) + def _reduce_88(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1804,16 +1846,16 @@ def _reduce_87(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 359) - def _reduce_88(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 363) + def _reduce_89(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 363) - def _reduce_89(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 367) + def _reduce_90(val, _values, result) token = val[3] token.alias_name = val[6] builder = val[0] @@ -1824,8 +1866,8 @@ def _reduce_89(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 371) - def _reduce_90(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 375) + def _reduce_91(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -1836,27 +1878,62 @@ def _reduce_90(val, _values, result) end .,., -# reduce 91 omitted +module_eval(<<'.,.,', 'parser.y', 383) + def _reduce_92(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 -# reduce 92 omitted + result + end +.,., -# reduce 93 omitted +module_eval(<<'.,.,', 'parser.y', 391) + def _reduce_93(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 94 omitted + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 398) + def _reduce_94(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 -module_eval(<<'.,.,', 'parser.y', 383) - def _reduce_95(val, _values, result) - result = val[1].s_value result end .,., +# reduce 95 omitted + # reduce 96 omitted # reduce 97 omitted -module_eval(<<'.,.,', 'parser.y', 390) - def _reduce_98(val, _values, result) +# reduce 98 omitted + +module_eval(<<'.,.,', 'parser.y', 410) + def _reduce_99(val, _values, result) + result = val[1].s_value + result + end +.,., + +# reduce 100 omitted + +# reduce 101 omitted + +module_eval(<<'.,.,', 'parser.y', 417) + def _reduce_102(val, _values, result) begin_c_declaration('\Z') @grammar.epilogue_first_lineno = @lexer.line + 1 @@ -1864,8 +1941,8 @@ def _reduce_98(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 395) - def _reduce_99(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 422) + def _reduce_103(val, _values, result) end_c_declaration @grammar.epilogue = val[2].s_value @@ -1873,36 +1950,54 @@ def _reduce_99(val, _values, result) end .,., -# reduce 100 omitted +# reduce 104 omitted -# reduce 101 omitted +# reduce 105 omitted -# reduce 102 omitted +# reduce 106 omitted -# reduce 103 omitted +# reduce 107 omitted -# reduce 104 omitted +# reduce 108 omitted -module_eval(<<'.,.,', 'parser.y', 406) - def _reduce_105(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 433) + def _reduce_109(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 407) - def _reduce_106(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 434) + def _reduce_110(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 107 omitted +# reduce 111 omitted -# reduce 108 omitted +# reduce 112 omitted -module_eval(<<'.,.,', 'parser.y', 412) - def _reduce_109(val, _values, result) +# reduce 113 omitted + +# reduce 114 omitted + +module_eval(<<'.,.,', 'parser.y', 442) + def _reduce_115(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 443) + def _reduce_116(val, _values, result) + result = val[0].append(val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 445) + def _reduce_117(val, _values, result) result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) result end diff --git a/parser.y b/parser.y index 2e36f342..d22151e9 100644 --- a/parser.y +++ b/parser.y @@ -68,6 +68,10 @@ rule { @grammar.initial_action = Grammar::Code::InitialActionCode.new(type: :initial_action, token_code: val[3]) } + | "%parser-state" IDENTIFIER "(" identifier_list_opt ")" + { + @grammar.add_parser_state(val[1], val[3]) + } | ";" grammar_declaration: "%union" "{" @@ -375,6 +379,29 @@ rule builder.precedence_sym = sym result = builder } + | rhs "%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 "%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 "%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: "?" | "+" @@ -410,6 +437,12 @@ rule generic_symlist_item: symbol | TAG + identifier_list_opt: # empty + | identifier_list + + 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]) } end 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..276e72e0 --- /dev/null +++ b/sig/lrama/grammar/parser_state.rbs @@ -0,0 +1,23 @@ +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_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 + end + end +end diff --git a/sig/lrama/grammar/rule_builder.rbs b/sig/lrama/grammar/rule_builder.rbs index b0a5b4e9..b24203eb 100644 --- a/sig/lrama/grammar/rule_builder.rbs +++ b/sig/lrama/grammar/rule_builder.rbs @@ -34,6 +34,7 @@ module Lrama def preprocess_references: () -> void def build_rules: () -> void def process_rhs: () -> void + def process_parser_state_token: (Lexer::Token, String, String, Integer) -> void def numberize_references: () -> void def flush_user_code: () -> void 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..57361aec --- /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 : %set(in_rescue, before_rescue) + %set(in_def, not_in_def) + %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 %push(in_rescue, after_rescue) + { printf("6 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + compstmt %pop(in_rescue) + { printf("7 => %s\n", YY_CURRENT_STATE_IN_RESCUE_NAME); } + | /* empty */ + ; + +opt_else : keyword_else %set(in_rescue, after_else) compstmt + | /* empty */ + ; + +opt_ensure : keyword_ensure %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 + %push(in_def, not_in_def) + %push(in_class, in_class) + cname + { + printf("1. cname => %s. in_def: %s, in_class: %s.\n", $4, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + compstmt + keyword_end + %pop(in_def) + %pop(in_class) + { + printf("2. cname => %s. in_def: %s, in_class: %s.\n", $4, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + | keyword_def + %push(in_def, in_def) + %push(in_class, not_in_class) + fname + { + printf("1. fname => %s. in_def: %s, in_class: %s.\n", $4, YY_CURRENT_STATE_IN_DEF_NAME, YY_CURRENT_STATE_IN_CLASS_NAME); + } + compstmt + keyword_end + %pop(in_def) + %pop(in_class) + { + printf("2. fname => %s. in_def: %s, in_class: %s.\n", $4, 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..297d6f38 --- /dev/null +++ b/spec/lrama/grammar/parser_state_spec.rb @@ -0,0 +1,157 @@ +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 + { + before_rescue, + after_rescue, + after_else, + 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 \\ + { \\ + YYDPRINTF ((stderr, "Push %s to in_rescue\\n", YY_STATE_IN_RESCUE_NAME (value))); \\ + *++yyparser_state_in_rescue_p = 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) \\ + { \\ + 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 (value))); \\ + *yyparser_state_in_rescue_p = value; \\ + } \\ + while (0) + + # define YY_STATE_IN_RESCUE yyparser_state_in_rescue_p + FUNC + end + end + + describe "#states_stacks" do + it "returns states stacks" do + expect(parser_state.states_stacks).to eq <<~STACKS + /* The parser state stack (yyparser_state_in_rescue): array, bottom, top. */ + int yyparser_state_in_rescue_a[YYINITDEPTH]; + int *yyparser_state_in_rescue = yyparser_state_in_rescue_a; + int *yyparser_state_in_rescue_p = yyparser_state_in_rescue; + 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 + before_rescue, + after_rescue, + after_else, + 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/integration_spec.rb b/spec/lrama/integration_spec.rb index 4d11b3ff..cb168f0a 100644 --- a/spec/lrama/integration_spec.rb +++ b/spec/lrama/integration_spec.rb @@ -30,7 +30,7 @@ def test_parser(parser_name, input, expected, lrama_command_args: [], debug: fal Open3.popen3(obj_path, input) do |stdin, stdout, stderr, wait_thr| out = stdout.read err = stderr.read - status = wait_thr.value + status = wait_thr.value end if debug @@ -111,6 +111,121 @@ 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 + 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. + 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) + + + # 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 0e17b46f..a5733718 100644 --- a/template/bison/yacc.c +++ b/template/bison/yacc.c @@ -461,6 +461,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. */ @@ -476,6 +479,10 @@ static const <%= output.int_type_for(output.context.yytranslate) %> yytranslate[ <%= output.yytranslate %> }; +<%- output.parser_states_functions.each do |func| -%> +<%= func %> +<%- end -%> + <%- if output.error_recovery -%> /* YYTRANSLATE_INVERTED[SYMBOL-NUM] -- Token number corresponding to SYMBOL-NUM */ static const <%= output.int_type_for(output.context.yytranslate_inverted) %> yytranslate_inverted[] = @@ -1512,6 +1519,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;