From 6b2c853077d26f252be3e14ed00a2366cca8fdba Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 12 Jan 2024 08:16:03 +0900 Subject: [PATCH] Provide functionalities for Bring Your Own Stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ruby’s Ripper library requires their own semantic value stack to manage Ruby Objects returned by user defined callback method. Currently Ripper uses semantic value stack (`yyvsa`) which is used by parser to manage Node. This hack introduces some limitation on Ripper. For example, Ripper can not execute semantic analysis depending on Node structure. Lrama introduces two features to support another semantic value stack by parser generator users. 1. Callback entry points User can emulate semantic value stack by these callbacks. Lrama provides these five callbacks. Registered functions are called when each event happen. For example %after-shift function is called when shift happens on original semantic value stack. * `%after-shift` function_name * `%before-reduce` function_name * `%after-reduce` function_name * `%after-shift-error-token` function_name * `%after-pop-stack` function_name 2. `$:n` variable to access index of each grammar symbols User also needs to access semantic value of their stack in grammar action. `$:n` provides the way to access to it. `$:n` is translated to the minus index from the top of the stack. For example ``` primary: k_if expr_value then compstmt if_tail k_end { /*% ripper: if!($:2, $:4, $:5) %*/ /* $:2 = -5, $:4 = -3, $:5 = -2. */ } ``` --- NEWS.md | 34 + lib/lrama/grammar.rb | 1 + lib/lrama/grammar/code/initial_action_code.rb | 6 + lib/lrama/grammar/code/no_reference_code.rb | 4 + lib/lrama/grammar/code/printer_code.rb | 6 + lib/lrama/grammar/code/rule_action.rb | 10 + lib/lrama/lexer.rb | 5 + lib/lrama/lexer/token/user_code.rb | 11 + lib/lrama/output.rb | 55 + lib/lrama/parser.rb | 977 ++++++++++-------- parser.y | 20 + spec/fixtures/integration/after_shift.l | 40 + spec/fixtures/integration/after_shift.y | 111 ++ spec/lrama/grammar/code_spec.rb | 67 ++ spec/lrama/integration_spec.rb | 61 ++ template/bison/yacc.c | 6 + 16 files changed, 957 insertions(+), 457 deletions(-) create mode 100644 spec/fixtures/integration/after_shift.l create mode 100644 spec/fixtures/integration/after_shift.y diff --git a/NEWS.md b/NEWS.md index 12244326..4b9f40e1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,39 @@ # NEWS for Lrama +## Lrama 0.6.3 (2024-02-xx) + +### Bring Your Own Stack + +Provide functionalities for Bring Your Own Stack. + +Ruby’s Ripper library requires their own semantic value stack to manage Ruby Objects returned by user defined callback method. Currently Ripper uses semantic value stack (`yyvsa`) which is used by parser to manage Node. This hack introduces some limitation on Ripper. For example, Ripper can not execute semantic analysis depending on Node structure. + +Lrama introduces two features to support another semantic value stack by parser generator users. + +1. Callback entry points + +User can emulate semantic value stack by these callbacks. +Lrama provides these five callbacks. Registered functions are called when each event happen. For example %after-shift function is called when shift happens on original semantic value stack. + +* `%after-shift` function_name +* `%before-reduce` function_name +* `%after-reduce` function_name +* `%after-shift-error-token` function_name +* `%after-pop-stack` function_name + +2. `$:n` variable to access index of each grammar symbols + +User also needs to access semantic value of their stack in grammar action. `$:n` provides the way to access to it. `$:n` is translated to the minus index from the top of the stack. +For example + +``` +primary: k_if expr_value then compstmt if_tail k_end + { + /*% ripper: if!($:2, $:4, $:5) %*/ + /* $:2 = -5, $:4 = -3, $:5 = -2. */ + } +``` + ## Lrama 0.6.2 (2024-01-27) ### %no-stdlib directive diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index 008cdfb1..7ccde1aa 100644 --- a/lib/lrama/grammar.rb +++ b/lib/lrama/grammar.rb @@ -26,6 +26,7 @@ class Grammar attr_accessor :union, :expect, :printers, :error_tokens, :lex_param, :parse_param, :initial_action, + :after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack, :symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib diff --git a/lib/lrama/grammar/code/initial_action_code.rb b/lib/lrama/grammar/code/initial_action_code.rb index 2b064f27..a694f193 100644 --- a/lib/lrama/grammar/code/initial_action_code.rb +++ b/lib/lrama/grammar/code/initial_action_code.rb @@ -6,18 +6,24 @@ class InitialActionCode < Code # * ($$) yylval # * (@$) yylloc + # * ($:$) error # * ($1) error # * (@1) error + # * ($:1) error def reference_to_c(ref) case when ref.type == :dollar && ref.name == "$" # $$ "yylval" when ref.type == :at && ref.name == "$" # @$ "yylloc" + when ref.type == :index && ref.name == "$" # $:$ + raise "$:#{ref.value} can not be used in initial_action." when ref.type == :dollar # $n raise "$#{ref.value} can not be used in initial_action." when ref.type == :at # @n raise "@#{ref.value} can not be used in initial_action." + when ref.type == :index # $:n + raise "$:#{ref.value} can not be used in initial_action." else raise "Unexpected. #{self}, #{ref}" end diff --git a/lib/lrama/grammar/code/no_reference_code.rb b/lib/lrama/grammar/code/no_reference_code.rb index ac6cdb8f..6e614cc6 100644 --- a/lib/lrama/grammar/code/no_reference_code.rb +++ b/lib/lrama/grammar/code/no_reference_code.rb @@ -6,14 +6,18 @@ class NoReferenceCode < Code # * ($$) error # * (@$) error + # * ($:$) error # * ($1) error # * (@1) error + # * ($:1) error def reference_to_c(ref) case when ref.type == :dollar # $$, $n raise "$#{ref.value} can not be used in #{type}." when ref.type == :at # @$, @n raise "@#{ref.value} can not be used in #{type}." + when ref.type == :index # $:$, $:n + raise "$:#{ref.value} can not be used in #{type}." else raise "Unexpected. #{self}, #{ref}" end diff --git a/lib/lrama/grammar/code/printer_code.rb b/lib/lrama/grammar/code/printer_code.rb index 2b1f127f..ffccd893 100644 --- a/lib/lrama/grammar/code/printer_code.rb +++ b/lib/lrama/grammar/code/printer_code.rb @@ -11,8 +11,10 @@ def initialize(type:, token_code:, tag:) # * ($$) *yyvaluep # * (@$) *yylocationp + # * ($:$) error # * ($1) error # * (@1) error + # * ($:1) error def reference_to_c(ref) case when ref.type == :dollar && ref.name == "$" # $$ @@ -20,10 +22,14 @@ def reference_to_c(ref) "((*yyvaluep).#{member})" when ref.type == :at && ref.name == "$" # @$ "(*yylocationp)" + when ref.type == :index && ref.name == "$" # $:$ + raise "$:#{ref.value} can not be used in #{type}." when ref.type == :dollar # $n raise "$#{ref.value} can not be used in #{type}." when ref.type == :at # @n raise "@#{ref.value} can not be used in #{type}." + when ref.type == :index # $:n + raise "$:#{ref.value} can not be used in #{type}." else raise "Unexpected. #{self}, #{ref}" end diff --git a/lib/lrama/grammar/code/rule_action.rb b/lib/lrama/grammar/code/rule_action.rb index 44194db0..d3c0eab6 100644 --- a/lib/lrama/grammar/code/rule_action.rb +++ b/lib/lrama/grammar/code/rule_action.rb @@ -11,8 +11,10 @@ def initialize(type:, token_code:, rule:) # * ($$) yyval # * (@$) yyloc + # * ($:$) error # * ($1) yyvsp[i] # * (@1) yylsp[i] + # * ($:1) i - 1 # # # Consider a rule like @@ -24,6 +26,8 @@ def initialize(type:, token_code:, rule:) # "Rule" class: keyword_class { $1 } tSTRING { $2 + $3 } keyword_end { $class = $1 + $keyword_end } # "Position in grammar" $1 $2 $3 $4 $5 # "Index for yyvsp" -4 -3 -2 -1 0 + # "$:n" $:1 $:2 $:3 $:4 $:5 + # "index of $:n" -5 -4 -3 -2 -1 # # # For the first midrule action: @@ -31,6 +35,7 @@ def initialize(type:, token_code:, rule:) # "Rule" class: keyword_class { $1 } tSTRING { $2 + $3 } keyword_end { $class = $1 + $keyword_end } # "Position in grammar" $1 # "Index for yyvsp" 0 + # "$:n" $:1 def reference_to_c(ref) case when ref.type == :dollar && ref.name == "$" # $$ @@ -39,6 +44,8 @@ def reference_to_c(ref) "(yyval.#{tag.member})" when ref.type == :at && ref.name == "$" # @$ "(yyloc)" + when ref.type == :index && ref.name == "$" # $:$ + raise "$:$ is not supported" when ref.type == :dollar # $n i = -position_in_rhs + ref.index tag = ref.ex_tag || rhs[ref.index - 1].tag @@ -47,6 +54,9 @@ def reference_to_c(ref) when ref.type == :at # @n i = -position_in_rhs + ref.index "(yylsp[#{i}])" + when ref.type == :index # $:n + i = -position_in_rhs + ref.index + "(#{i} - 1)" else raise "Unexpected. #{self}, #{ref}" end diff --git a/lib/lrama/lexer.rb b/lib/lrama/lexer.rb index b94fad57..33f37eb6 100644 --- a/lib/lrama/lexer.rb +++ b/lib/lrama/lexer.rb @@ -27,6 +27,11 @@ class Lexer %precedence %prec %error-token + %before-reduce + %after-reduce + %after-shift-error-token + %after-shift + %after-pop-stack %empty %code %rule diff --git a/lib/lrama/lexer/token/user_code.rb b/lib/lrama/lexer/token/user_code.rb index 765ca2fb..ec2acd50 100644 --- a/lib/lrama/lexer/token/user_code.rb +++ b/lib/lrama/lexer/token/user_code.rb @@ -56,6 +56,17 @@ def scan_reference(scanner) return Lrama::Grammar::Reference.new(type: :at, name: scanner[1], first_column: start, last_column: scanner.pos) when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @[expr.right], @[expr-right] (named reference with brackets) return Lrama::Grammar::Reference.new(type: :at, name: scanner[1], first_column: start, last_column: scanner.pos) + + # $: references + when scanner.scan(/\$:\$/) # $:$ + return Lrama::Grammar::Reference.new(type: :index, name: "$", first_column: start, last_column: scanner.pos) + when scanner.scan(/\$:(\d+)/) # $:1 + return Lrama::Grammar::Reference.new(type: :index, index: Integer(scanner[1]), first_column: start, last_column: scanner.pos) + when scanner.scan(/\$:([a-zA-Z_][a-zA-Z0-9_]*)/) # $:foo, $:expr (named reference without brackets) + return Lrama::Grammar::Reference.new(type: :index, name: scanner[1], first_column: start, last_column: scanner.pos) + when scanner.scan(/\$:\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $:[expr.right], $:[expr-right] (named reference with brackets) + return Lrama::Grammar::Reference.new(type: :index, name: scanner[1], first_column: start, last_column: scanner.pos) + end end end diff --git a/lib/lrama/output.rb b/lib/lrama/output.rb index c4c7c0bb..29bf1e69 100644 --- a/lib/lrama/output.rb +++ b/lib/lrama/output.rb @@ -161,6 +161,61 @@ def user_initial_action(comment = "") STR end + def after_shift_function(comment = "") + return "" unless @grammar.after_shift + + <<-STR + #{comment} +#line #{@grammar.after_shift.line} "#{@grammar_file_path}" + {#{@grammar.after_shift.s_value}(#{parse_param_name});} +#line [@oline@] [@ofile@] + STR + end + + def before_reduce_function(comment = "") + return "" unless @grammar.before_reduce + + <<-STR + #{comment} +#line #{@grammar.before_reduce.line} "#{@grammar_file_path}" + {#{@grammar.before_reduce.s_value}(yylen#{user_args});} +#line [@oline@] [@ofile@] + STR + end + + def after_reduce_function(comment = "") + return "" unless @grammar.after_reduce + + <<-STR + #{comment} +#line #{@grammar.after_reduce.line} "#{@grammar_file_path}" + {#{@grammar.after_reduce.s_value}(yylen#{user_args});} +#line [@oline@] [@ofile@] + STR + end + + def after_shift_error_token_function(comment = "") + return "" unless @grammar.after_shift_error_token + + <<-STR + #{comment} +#line #{@grammar.after_shift_error_token.line} "#{@grammar_file_path}" + {#{@grammar.after_shift_error_token.s_value}(#{parse_param_name});} +#line [@oline@] [@ofile@] + STR + end + + def after_pop_stack_function(len, comment = "") + return "" unless @grammar.after_pop_stack + + <<-STR + #{comment} +#line #{@grammar.after_pop_stack.line} "#{@grammar_file_path}" + {#{@grammar.after_pop_stack.s_value}(#{len}#{user_args});} +#line [@oline@] [@ofile@] + STR + end + def symbol_actions_for_error_token str = "" diff --git a/lib/lrama/parser.rb b/lib/lrama/parser.rb index e5f2384e..148457f1 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', 501) +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 521) include Lrama::Report::Duration @@ -732,303 +732,316 @@ def raise_parse_error(error_message, location) ##### State transition tables begin ### racc_action_table = [ - 86, 45, 87, 146, 145, 68, 45, 45, 146, 189, - 68, 68, 45, 6, 189, 7, 68, 148, 200, 45, - 144, 44, 148, 190, 59, 164, 165, 166, 190, 3, - 45, 41, 44, 8, 68, 64, 35, 42, 45, 149, - 44, 41, 88, 71, 149, 191, 81, 45, 48, 44, - 191, 22, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 22, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 9, 45, 48, 44, 13, 14, 15, 16, 17, - 18, 48, 51, 19, 20, 21, 22, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 45, 45, 44, - 44, 52, 71, 71, 45, 45, 44, 44, 45, 71, - 44, 53, 68, 174, 45, 45, 44, 44, 68, 174, - 45, 45, 44, 44, 68, 174, 45, 45, 44, 44, - 68, 174, 45, 45, 44, 44, 68, 174, 45, 45, - 44, 44, 68, 174, 45, 45, 44, 44, 68, 68, - 45, 45, 44, 44, 68, 68, 45, 45, 44, 44, - 68, 68, 45, 45, 180, 44, 68, 68, 45, 45, - 180, 44, 68, 68, 45, 45, 180, 44, 68, 164, - 165, 166, 84, 45, 45, 44, 44, 142, 193, 143, - 194, 164, 165, 166, 209, 211, 194, 194, 54, 55, - 56, 77, 78, 82, 84, 89, 89, 89, 91, 97, - 101, 102, 105, 105, 105, 105, 108, 111, 112, 114, - 116, 117, 118, 119, 120, 123, 127, 128, 129, 132, - 133, 134, 136, 151, 153, 154, 155, 156, 157, 158, - 159, 132, 161, 169, 170, 179, 184, 185, 187, 192, - 179, 84, 184, 206, 208, 84, 213, 84 ] + 96, 50, 97, 156, 155, 78, 50, 50, 156, 199, + 78, 78, 50, 50, 199, 49, 78, 158, 69, 6, + 3, 7, 158, 200, 210, 154, 8, 50, 200, 49, + 40, 174, 175, 176, 47, 50, 46, 49, 53, 78, + 74, 50, 53, 49, 159, 53, 81, 98, 56, 159, + 201, 174, 175, 176, 94, 201, 22, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 46, 50, 50, 49, 49, 91, 81, 81, 50, + 50, 49, 49, 50, 81, 49, 57, 78, 184, 58, + 59, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 9, 50, 60, 49, + 13, 14, 15, 16, 17, 18, 61, 62, 19, 20, + 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 50, 50, 49, + 49, 78, 184, 50, 50, 49, 49, 78, 184, 50, + 50, 49, 49, 78, 184, 50, 50, 49, 49, 78, + 184, 50, 50, 49, 49, 78, 184, 50, 50, 49, + 49, 78, 78, 50, 50, 49, 49, 78, 78, 50, + 50, 49, 49, 78, 78, 50, 50, 190, 49, 78, + 78, 50, 50, 190, 49, 78, 78, 50, 50, 190, + 49, 78, 50, 50, 49, 49, 152, 203, 153, 204, + 174, 175, 176, 219, 221, 204, 204, 63, 64, 65, + 66, 87, 88, 92, 94, 99, 99, 99, 101, 107, + 111, 112, 115, 115, 115, 115, 118, 121, 122, 124, + 126, 127, 128, 129, 130, 133, 137, 138, 139, 142, + 143, 144, 146, 161, 163, 164, 165, 166, 167, 168, + 169, 142, 171, 179, 180, 189, 194, 195, 197, 202, + 189, 94, 194, 216, 218, 94, 223, 94 ] racc_action_check = [ - 43, 131, 43, 131, 130, 131, 160, 178, 160, 178, - 160, 178, 197, 2, 197, 2, 197, 131, 189, 27, - 130, 27, 160, 178, 27, 189, 189, 189, 197, 1, - 28, 9, 28, 3, 28, 28, 7, 13, 29, 131, - 29, 36, 43, 29, 160, 178, 36, 14, 15, 14, - 197, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 4, 58, 16, 58, 4, 4, 4, 4, 4, - 4, 17, 18, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 30, 31, 30, - 31, 19, 30, 31, 32, 59, 32, 59, 155, 32, - 155, 22, 155, 155, 156, 70, 156, 70, 156, 156, - 157, 71, 157, 71, 157, 157, 171, 97, 171, 97, - 171, 171, 175, 99, 175, 99, 175, 175, 176, 105, - 176, 105, 176, 176, 63, 64, 63, 64, 63, 64, - 102, 104, 102, 104, 102, 104, 124, 149, 124, 149, - 124, 149, 161, 191, 161, 191, 161, 191, 192, 194, - 192, 194, 192, 194, 200, 107, 200, 107, 200, 147, - 147, 147, 147, 121, 125, 121, 125, 126, 181, 126, - 181, 182, 182, 182, 203, 207, 203, 207, 24, 25, - 26, 33, 34, 39, 40, 47, 49, 50, 51, 57, - 61, 62, 69, 74, 75, 76, 77, 83, 84, 90, - 92, 93, 94, 95, 96, 100, 108, 109, 110, 111, - 112, 113, 115, 135, 137, 138, 139, 140, 141, 142, - 143, 144, 146, 150, 152, 158, 163, 167, 177, 180, - 187, 188, 193, 196, 201, 206, 212, 213 ] + 48, 141, 48, 141, 140, 141, 170, 188, 170, 188, + 170, 188, 207, 32, 207, 32, 207, 141, 32, 2, + 1, 2, 170, 188, 199, 140, 3, 14, 207, 14, + 7, 199, 199, 199, 13, 33, 9, 33, 15, 33, + 33, 34, 16, 34, 141, 17, 34, 48, 18, 170, + 188, 157, 157, 157, 157, 207, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 41, 35, 36, 35, 36, 41, 35, 36, 37, + 68, 37, 68, 165, 37, 165, 19, 165, 165, 22, + 24, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 4, 69, 25, 69, + 4, 4, 4, 4, 4, 4, 26, 27, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 166, 80, 166, + 80, 166, 166, 167, 81, 167, 81, 167, 167, 181, + 107, 181, 107, 181, 181, 185, 109, 185, 109, 185, + 185, 186, 115, 186, 115, 186, 186, 73, 74, 73, + 74, 73, 74, 112, 114, 112, 114, 112, 114, 134, + 159, 134, 159, 134, 159, 171, 201, 171, 201, 171, + 201, 202, 204, 202, 204, 202, 204, 210, 117, 210, + 117, 210, 131, 135, 131, 135, 136, 191, 136, 191, + 192, 192, 192, 213, 217, 213, 217, 28, 29, 30, + 31, 38, 39, 44, 45, 52, 54, 55, 56, 67, + 71, 72, 79, 84, 85, 86, 87, 93, 94, 100, + 102, 103, 104, 105, 106, 110, 118, 119, 120, 121, + 122, 123, 125, 145, 147, 148, 149, 150, 151, 152, + 153, 154, 156, 160, 162, 168, 173, 177, 187, 190, + 197, 198, 203, 206, 211, 216, 222, 223 ] racc_action_pointer = [ - nil, 29, 3, 33, 62, nil, nil, 29, nil, 27, - nil, nil, nil, 31, 44, 29, 54, 62, 77, 82, - nil, nil, 92, nil, 179, 180, 181, 16, 27, 35, - 94, 95, 101, 196, 200, nil, 37, nil, nil, 180, - 159, nil, nil, -5, nil, nil, nil, 186, nil, 187, - 188, 189, nil, nil, nil, nil, nil, 201, 69, 102, - nil, 204, 203, 141, 142, nil, nil, nil, nil, 204, - 112, 118, nil, nil, 205, 206, 207, 181, nil, nil, - nil, nil, nil, 180, 213, nil, nil, nil, nil, nil, - 217, nil, 218, 219, 220, 221, 222, 124, nil, 130, - 218, nil, 147, nil, 148, 136, nil, 172, 221, 216, - 226, 189, 184, 229, nil, 230, nil, nil, nil, nil, - nil, 180, nil, nil, 153, 181, 151, nil, nil, nil, - -19, -2, nil, nil, nil, 213, nil, 214, 215, 216, - 217, 218, 202, 235, 201, nil, 207, 137, nil, 154, - 223, nil, 224, nil, nil, 105, 111, 117, 205, nil, - 3, 159, nil, 238, nil, nil, nil, 245, nil, nil, - nil, 123, nil, nil, nil, 129, 135, 209, 4, nil, - 214, 152, 149, nil, nil, nil, nil, 210, 206, -17, - nil, 160, 165, 244, 166, nil, 233, 9, nil, nil, - 171, 252, nil, 158, nil, nil, 210, 159, nil, nil, - nil, nil, 236, 212, nil ] + nil, 20, 9, 26, 97, nil, nil, 23, nil, 32, + nil, nil, nil, 28, 24, 19, 23, 26, 43, 67, + nil, nil, 70, nil, 71, 89, 97, 112, 212, 213, + 214, 215, 10, 32, 38, 69, 70, 76, 216, 220, + nil, 67, nil, nil, 200, 174, nil, nil, -5, nil, + nil, nil, 206, nil, 207, 208, 209, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 221, 77, 104, + nil, 224, 223, 164, 165, nil, nil, nil, nil, 224, + 135, 141, nil, nil, 225, 226, 227, 196, nil, nil, + nil, nil, nil, 195, 233, nil, nil, nil, nil, nil, + 237, nil, 238, 239, 240, 241, 242, 147, nil, 153, + 238, nil, 170, nil, 171, 159, nil, 195, 241, 236, + 246, 204, 199, 249, nil, 250, nil, nil, nil, nil, + nil, 199, nil, nil, 176, 200, 165, nil, nil, nil, + -19, -2, nil, nil, nil, 233, nil, 234, 235, 236, + 237, 238, 217, 255, 216, nil, 222, 4, nil, 177, + 243, nil, 244, nil, nil, 80, 134, 140, 220, nil, + 3, 182, nil, 258, nil, nil, nil, 265, nil, nil, + nil, 146, nil, nil, nil, 152, 158, 224, 4, nil, + 229, 166, 163, nil, nil, nil, nil, 225, 221, -16, + nil, 183, 188, 264, 189, nil, 253, 9, nil, nil, + 194, 272, nil, 172, nil, nil, 225, 173, nil, nil, + nil, nil, 256, 227, nil ] racc_action_default = [ - -2, -131, -8, -131, -131, -3, -4, -131, 215, -131, - -9, -10, -11, -131, -131, -131, -131, -131, -131, -131, - -23, -24, -131, -28, -131, -131, -131, -131, -131, -131, - -131, -131, -131, -131, -131, -7, -116, -89, -91, -131, - -113, -115, -12, -120, -87, -88, -119, -14, -78, -15, - -16, -131, -20, -25, -29, -32, -35, -38, -44, -131, - -47, -64, -39, -68, -131, -71, -73, -74, -128, -40, - -81, -131, -84, -86, -41, -42, -43, -131, -5, -1, - -90, -117, -92, -131, -131, -13, -121, -122, -123, -75, - -131, -17, -131, -131, -131, -131, -131, -131, -48, -45, - -66, -65, -131, -72, -69, -131, -85, -82, -131, -131, - -131, -97, -131, -131, -79, -131, -21, -26, -30, -33, - -36, -46, -49, -67, -70, -83, -131, -51, -6, -118, - -93, -94, -98, -114, -76, -131, -18, -131, -131, -131, - -131, -131, -131, -131, -97, -96, -87, -113, -102, -131, - -131, -80, -131, -22, -27, -131, -131, -131, -55, -52, - -95, -131, -99, -129, -106, -107, -108, -131, -105, -77, - -19, -31, -124, -126, -127, -34, -37, -50, -53, -56, - -87, -131, -109, -100, -130, -103, -125, -55, -113, -87, - -60, -131, -131, -129, -131, -111, -131, -54, -57, -58, - -131, -131, -63, -131, -101, -110, -113, -131, -61, -112, - -104, -59, -131, -113, -62 ] + -2, -136, -8, -136, -136, -3, -4, -136, 225, -136, + -9, -10, -11, -136, -136, -136, -136, -136, -136, -136, + -23, -24, -136, -28, -136, -136, -136, -136, -136, -136, + -136, -136, -136, -136, -136, -136, -136, -136, -136, -136, + -7, -121, -94, -96, -136, -118, -120, -12, -125, -92, + -93, -124, -14, -83, -15, -16, -136, -20, -25, -29, + -32, -35, -38, -39, -40, -41, -42, -43, -49, -136, + -52, -69, -44, -73, -136, -76, -78, -79, -133, -45, + -86, -136, -89, -91, -46, -47, -48, -136, -5, -1, + -95, -122, -97, -136, -136, -13, -126, -127, -128, -80, + -136, -17, -136, -136, -136, -136, -136, -136, -53, -50, + -71, -70, -136, -77, -74, -136, -90, -87, -136, -136, + -136, -102, -136, -136, -84, -136, -21, -26, -30, -33, + -36, -51, -54, -72, -75, -88, -136, -56, -6, -123, + -98, -99, -103, -119, -81, -136, -18, -136, -136, -136, + -136, -136, -136, -136, -102, -101, -92, -118, -107, -136, + -136, -85, -136, -22, -27, -136, -136, -136, -60, -57, + -100, -136, -104, -134, -111, -112, -113, -136, -110, -82, + -19, -31, -129, -131, -132, -34, -37, -55, -58, -61, + -92, -136, -114, -105, -135, -108, -130, -60, -118, -92, + -65, -136, -136, -134, -136, -116, -136, -59, -62, -63, + -136, -136, -68, -136, -106, -115, -118, -136, -66, -117, + -109, -64, -136, -118, -67 ] racc_goto_table = [ - 83, 63, 46, 58, 98, 65, 106, 163, 183, 37, - 178, 1, 2, 181, 107, 61, 4, 73, 73, 73, - 73, 131, 186, 47, 49, 50, 186, 186, 69, 74, - 75, 76, 171, 175, 176, 99, 80, 104, 204, 197, - 103, 65, 195, 106, 203, 98, 61, 61, 125, 199, - 36, 79, 207, 5, 160, 34, 109, 10, 73, 73, - 11, 106, 12, 43, 85, 115, 152, 98, 92, 137, - 93, 138, 94, 121, 139, 124, 95, 140, 96, 65, - 141, 103, 57, 62, 100, 61, 122, 61, 126, 177, - 201, 212, 113, 73, 150, 73, 90, 135, 130, 167, - 196, 103, 110, nil, nil, nil, nil, 162, 147, 61, - nil, nil, nil, 73, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 168, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 147, 182, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 198, nil, - nil, nil, nil, nil, nil, 188, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 210, nil, 202, 182, - nil, 205, nil, 214, 188, nil, nil, 182 ] + 93, 51, 73, 68, 116, 75, 108, 173, 193, 1, + 188, 196, 2, 191, 117, 196, 196, 141, 4, 71, + 41, 83, 83, 83, 83, 42, 79, 84, 85, 86, + 52, 54, 55, 181, 185, 186, 89, 5, 214, 207, + 109, 116, 205, 114, 213, 113, 75, 108, 135, 209, + 170, 39, 217, 119, 10, 71, 71, 90, 11, 116, + 12, 48, 95, 125, 162, 102, 147, 83, 83, 108, + 103, 148, 104, 149, 105, 150, 106, 151, 131, 67, + 72, 134, 110, 132, 75, 136, 113, 187, 211, 222, + 123, 160, 100, 145, 71, 140, 71, 177, 206, 120, + nil, nil, 83, nil, 83, nil, 113, nil, nil, nil, + nil, nil, 172, 157, nil, nil, nil, nil, 71, nil, + nil, nil, 83, nil, nil, nil, nil, nil, nil, nil, + nil, 178, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, 157, 192, nil, nil, nil, nil, nil, nil, + nil, nil, nil, 208, nil, nil, nil, nil, nil, nil, + 198, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, 220, nil, 212, 192, nil, 215, nil, 224, 198, + nil, nil, 192 ] racc_goto_check = [ - 41, 46, 34, 32, 33, 40, 53, 42, 59, 54, - 39, 1, 2, 43, 52, 34, 3, 34, 34, 34, - 34, 58, 63, 14, 14, 14, 63, 63, 31, 31, - 31, 31, 20, 20, 20, 32, 54, 46, 59, 39, - 40, 40, 42, 53, 43, 33, 34, 34, 52, 42, - 4, 5, 43, 6, 58, 7, 8, 9, 34, 34, - 10, 53, 11, 12, 13, 15, 16, 33, 17, 18, - 21, 22, 23, 32, 24, 46, 25, 26, 27, 40, - 28, 40, 29, 30, 35, 34, 36, 34, 37, 38, - 44, 45, 48, 34, 49, 34, 50, 51, 57, 60, - 61, 40, 62, nil, nil, nil, nil, 41, 40, 34, - nil, nil, nil, 34, nil, nil, nil, nil, 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, nil, nil, nil, 41, nil, - nil, nil, nil, nil, nil, 40, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 41, nil, 40, 40, - nil, 40, nil, 41, 40, nil, nil, 40 ] + 41, 34, 46, 32, 53, 40, 33, 42, 59, 1, + 39, 63, 2, 43, 52, 63, 63, 58, 3, 34, + 4, 34, 34, 34, 34, 54, 31, 31, 31, 31, + 14, 14, 14, 20, 20, 20, 5, 6, 59, 39, + 32, 53, 42, 46, 43, 40, 40, 33, 52, 42, + 58, 7, 43, 8, 9, 34, 34, 54, 10, 53, + 11, 12, 13, 15, 16, 17, 18, 34, 34, 33, + 21, 22, 23, 24, 25, 26, 27, 28, 32, 29, + 30, 46, 35, 36, 40, 37, 40, 38, 44, 45, + 48, 49, 50, 51, 34, 57, 34, 60, 61, 62, + nil, nil, 34, nil, 34, nil, 40, nil, nil, nil, + nil, nil, 41, 40, nil, nil, nil, nil, 34, nil, + nil, nil, 34, 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, + nil, nil, nil, 41, nil, nil, nil, nil, nil, nil, + 40, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, 41, nil, 40, 40, nil, 40, nil, 41, 40, + nil, nil, 40 ] racc_goto_pointer = [ - nil, 11, 12, 14, 41, 15, 51, 49, -22, 53, - 56, 58, 49, 21, 8, -26, -70, 16, -47, nil, - -123, 17, -46, 18, -44, 21, -42, 22, -40, 55, - 55, -1, -24, -54, -12, 23, -14, -20, -69, -148, - -23, -40, -140, -148, -100, -117, -27, nil, 3, -40, - 48, -17, -57, -64, 0, nil, nil, -13, -90, -155, - -49, -85, 21, -149 ] + nil, 9, 12, 16, 11, -5, 35, 45, -35, 50, + 54, 56, 47, 14, 15, -38, -82, 8, -60, nil, + -132, 12, -56, 13, -55, 14, -54, 15, -53, 47, + 47, -8, -29, -62, -13, 11, -27, -33, -81, -158, + -28, -45, -150, -158, -112, -129, -31, nil, -9, -53, + 39, -31, -67, -76, 16, nil, nil, -26, -104, -165, + -61, -97, 8, -170 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 39, nil, nil, nil, nil, nil, nil, nil, nil, 23, + 44, nil, nil, nil, nil, nil, nil, nil, nil, 23, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 60, 66, nil, nil, nil, nil, nil, - 173, nil, nil, nil, nil, nil, nil, 67, nil, nil, - nil, nil, 70, 72, nil, 38, 40, nil, nil, nil, - nil, nil, nil, 172 ] + nil, nil, nil, 70, 76, nil, nil, nil, nil, nil, + 183, nil, nil, nil, nil, nil, nil, 77, nil, nil, + nil, nil, 80, 82, nil, 43, 45, nil, nil, nil, + nil, nil, nil, 182 ] racc_reduce_table = [ 0, 0, :racc_error, - 5, 49, :_reduce_none, - 0, 50, :_reduce_none, - 2, 50, :_reduce_none, - 0, 55, :_reduce_4, - 0, 56, :_reduce_5, - 5, 54, :_reduce_6, - 2, 54, :_reduce_none, - 0, 51, :_reduce_8, - 2, 51, :_reduce_none, - 1, 57, :_reduce_none, - 1, 57, :_reduce_none, - 2, 57, :_reduce_12, - 3, 57, :_reduce_none, - 2, 57, :_reduce_none, - 2, 57, :_reduce_15, - 2, 57, :_reduce_16, - 0, 63, :_reduce_17, - 0, 64, :_reduce_18, - 7, 57, :_reduce_19, - 0, 65, :_reduce_20, - 0, 66, :_reduce_21, - 6, 57, :_reduce_22, - 1, 57, :_reduce_23, - 1, 57, :_reduce_none, - 0, 69, :_reduce_25, - 0, 70, :_reduce_26, - 6, 58, :_reduce_27, - 1, 58, :_reduce_none, - 0, 71, :_reduce_29, - 0, 72, :_reduce_30, - 7, 58, :_reduce_none, - 0, 73, :_reduce_32, - 0, 74, :_reduce_33, - 7, 58, :_reduce_34, - 0, 75, :_reduce_35, - 0, 76, :_reduce_36, - 7, 58, :_reduce_37, - 2, 67, :_reduce_none, - 2, 67, :_reduce_39, - 2, 67, :_reduce_40, - 2, 67, :_reduce_41, - 2, 67, :_reduce_42, - 2, 67, :_reduce_43, - 1, 77, :_reduce_44, - 2, 77, :_reduce_45, - 3, 77, :_reduce_46, - 1, 80, :_reduce_47, - 2, 80, :_reduce_48, - 3, 81, :_reduce_49, - 7, 59, :_reduce_50, - 1, 85, :_reduce_51, - 3, 85, :_reduce_52, - 1, 86, :_reduce_53, + 5, 54, :_reduce_none, + 0, 55, :_reduce_none, + 2, 55, :_reduce_none, + 0, 60, :_reduce_4, + 0, 61, :_reduce_5, + 5, 59, :_reduce_6, + 2, 59, :_reduce_none, + 0, 56, :_reduce_8, + 2, 56, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 2, 62, :_reduce_12, + 3, 62, :_reduce_none, + 2, 62, :_reduce_none, + 2, 62, :_reduce_15, + 2, 62, :_reduce_16, + 0, 68, :_reduce_17, + 0, 69, :_reduce_18, + 7, 62, :_reduce_19, + 0, 70, :_reduce_20, + 0, 71, :_reduce_21, + 6, 62, :_reduce_22, + 1, 62, :_reduce_23, + 1, 62, :_reduce_none, + 0, 74, :_reduce_25, + 0, 75, :_reduce_26, + 6, 63, :_reduce_27, + 1, 63, :_reduce_none, + 0, 76, :_reduce_29, + 0, 77, :_reduce_30, + 7, 63, :_reduce_none, + 0, 78, :_reduce_32, + 0, 79, :_reduce_33, + 7, 63, :_reduce_34, + 0, 80, :_reduce_35, + 0, 81, :_reduce_36, + 7, 63, :_reduce_37, + 2, 63, :_reduce_38, + 2, 63, :_reduce_39, + 2, 63, :_reduce_40, + 2, 63, :_reduce_41, + 2, 63, :_reduce_42, + 2, 72, :_reduce_none, + 2, 72, :_reduce_44, + 2, 72, :_reduce_45, + 2, 72, :_reduce_46, + 2, 72, :_reduce_47, + 2, 72, :_reduce_48, + 1, 82, :_reduce_49, + 2, 82, :_reduce_50, + 3, 82, :_reduce_51, + 1, 85, :_reduce_52, + 2, 85, :_reduce_53, 3, 86, :_reduce_54, - 0, 87, :_reduce_55, - 1, 87, :_reduce_56, - 3, 87, :_reduce_57, - 3, 87, :_reduce_58, - 5, 87, :_reduce_59, + 7, 64, :_reduce_55, + 1, 90, :_reduce_56, + 3, 90, :_reduce_57, + 1, 91, :_reduce_58, + 3, 91, :_reduce_59, 0, 92, :_reduce_60, - 0, 93, :_reduce_61, - 7, 87, :_reduce_62, - 3, 87, :_reduce_63, - 0, 83, :_reduce_none, - 1, 83, :_reduce_none, - 0, 84, :_reduce_none, - 1, 84, :_reduce_none, - 1, 78, :_reduce_68, - 2, 78, :_reduce_69, - 3, 78, :_reduce_70, - 1, 94, :_reduce_71, - 2, 94, :_reduce_72, - 1, 88, :_reduce_none, + 1, 92, :_reduce_61, + 3, 92, :_reduce_62, + 3, 92, :_reduce_63, + 5, 92, :_reduce_64, + 0, 97, :_reduce_65, + 0, 98, :_reduce_66, + 7, 92, :_reduce_67, + 3, 92, :_reduce_68, + 0, 88, :_reduce_none, 1, 88, :_reduce_none, - 0, 96, :_reduce_75, - 0, 97, :_reduce_76, - 6, 62, :_reduce_77, - 0, 98, :_reduce_78, - 0, 99, :_reduce_79, - 5, 62, :_reduce_80, - 1, 79, :_reduce_81, - 2, 79, :_reduce_82, - 3, 79, :_reduce_83, - 1, 100, :_reduce_84, - 2, 100, :_reduce_85, - 1, 101, :_reduce_none, - 1, 82, :_reduce_87, - 1, 82, :_reduce_88, - 1, 52, :_reduce_none, - 2, 52, :_reduce_none, - 1, 102, :_reduce_none, - 2, 102, :_reduce_none, - 4, 103, :_reduce_93, - 1, 105, :_reduce_94, - 3, 105, :_reduce_95, - 2, 105, :_reduce_none, - 0, 106, :_reduce_97, - 1, 106, :_reduce_98, - 3, 106, :_reduce_99, - 4, 106, :_reduce_100, - 6, 106, :_reduce_101, - 0, 108, :_reduce_102, - 0, 109, :_reduce_103, - 7, 106, :_reduce_104, - 3, 106, :_reduce_105, - 1, 90, :_reduce_106, - 1, 90, :_reduce_107, - 1, 90, :_reduce_108, - 1, 91, :_reduce_109, - 3, 91, :_reduce_110, - 2, 91, :_reduce_111, - 4, 91, :_reduce_112, 0, 89, :_reduce_none, - 3, 89, :_reduce_114, - 1, 104, :_reduce_none, - 0, 53, :_reduce_none, - 0, 110, :_reduce_117, - 3, 53, :_reduce_118, - 1, 60, :_reduce_none, - 0, 61, :_reduce_none, - 1, 61, :_reduce_none, - 1, 61, :_reduce_none, - 1, 61, :_reduce_none, - 1, 68, :_reduce_124, - 2, 68, :_reduce_125, - 1, 111, :_reduce_none, - 1, 111, :_reduce_none, - 1, 95, :_reduce_128, - 0, 107, :_reduce_none, - 1, 107, :_reduce_none ] - -racc_reduce_n = 131 - -racc_shift_n = 215 + 1, 89, :_reduce_none, + 1, 83, :_reduce_73, + 2, 83, :_reduce_74, + 3, 83, :_reduce_75, + 1, 99, :_reduce_76, + 2, 99, :_reduce_77, + 1, 93, :_reduce_none, + 1, 93, :_reduce_none, + 0, 101, :_reduce_80, + 0, 102, :_reduce_81, + 6, 67, :_reduce_82, + 0, 103, :_reduce_83, + 0, 104, :_reduce_84, + 5, 67, :_reduce_85, + 1, 84, :_reduce_86, + 2, 84, :_reduce_87, + 3, 84, :_reduce_88, + 1, 105, :_reduce_89, + 2, 105, :_reduce_90, + 1, 106, :_reduce_none, + 1, 87, :_reduce_92, + 1, 87, :_reduce_93, + 1, 57, :_reduce_none, + 2, 57, :_reduce_none, + 1, 107, :_reduce_none, + 2, 107, :_reduce_none, + 4, 108, :_reduce_98, + 1, 110, :_reduce_99, + 3, 110, :_reduce_100, + 2, 110, :_reduce_none, + 0, 111, :_reduce_102, + 1, 111, :_reduce_103, + 3, 111, :_reduce_104, + 4, 111, :_reduce_105, + 6, 111, :_reduce_106, + 0, 113, :_reduce_107, + 0, 114, :_reduce_108, + 7, 111, :_reduce_109, + 3, 111, :_reduce_110, + 1, 95, :_reduce_111, + 1, 95, :_reduce_112, + 1, 95, :_reduce_113, + 1, 96, :_reduce_114, + 3, 96, :_reduce_115, + 2, 96, :_reduce_116, + 4, 96, :_reduce_117, + 0, 94, :_reduce_none, + 3, 94, :_reduce_119, + 1, 109, :_reduce_none, + 0, 58, :_reduce_none, + 0, 115, :_reduce_122, + 3, 58, :_reduce_123, + 1, 65, :_reduce_none, + 0, 66, :_reduce_none, + 1, 66, :_reduce_none, + 1, 66, :_reduce_none, + 1, 66, :_reduce_none, + 1, 73, :_reduce_129, + 2, 73, :_reduce_130, + 1, 116, :_reduce_none, + 1, 116, :_reduce_none, + 1, 100, :_reduce_133, + 0, 112, :_reduce_none, + 1, 112, :_reduce_none ] + +racc_reduce_n = 136 + +racc_shift_n = 225 racc_token_table = { false => 0, @@ -1059,28 +1072,33 @@ def raise_parse_error(error_message, location) "%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, - "?" => 42, - "+" => 43, - "*" => 44, - "[" => 45, - "]" => 46, - "{...}" => 47 } - -racc_nt_base = 48 + "%after-shift" => 28, + "%before-reduce" => 29, + "%after-reduce" => 30, + "%after-shift-error-token" => 31, + "%after-pop-stack" => 32, + "%token" => 33, + "%type" => 34, + "%left" => 35, + "%right" => 36, + "%precedence" => 37, + "%nonassoc" => 38, + "%rule" => 39, + "(" => 40, + ")" => 41, + ":" => 42, + "," => 43, + "|" => 44, + "%empty" => 45, + "%prec" => 46, + "?" => 47, + "+" => 48, + "*" => 49, + "[" => 50, + "]" => 51, + "{...}" => 52 } + +racc_nt_base = 53 racc_use_result_var = true @@ -1130,6 +1148,11 @@ def raise_parse_error(error_message, location) "\"%destructor\"", "\"%printer\"", "\"%error-token\"", + "\"%after-shift\"", + "\"%before-reduce\"", + "\"%after-reduce\"", + "\"%after-shift-error-token\"", + "\"%after-pop-stack\"", "\"%token\"", "\"%type\"", "\"%left\"", @@ -1459,10 +1482,50 @@ def _reduce_37(val, _values, result) end .,., -# reduce 38 omitted +module_eval(<<'.,.,', 'parser.y', 133) + def _reduce_38(val, _values, result) + @grammar.after_shift = val[1] + + result + end +.,., -module_eval(<<'.,.,', 'parser.y', 135) +module_eval(<<'.,.,', 'parser.y', 137) def _reduce_39(val, _values, result) + @grammar.before_reduce = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 141) + def _reduce_40(val, _values, result) + @grammar.after_reduce = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 145) + def _reduce_41(val, _values, result) + @grammar.after_shift_error_token = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 149) + def _reduce_42(val, _values, result) + @grammar.after_pop_stack = val[1] + + result + end +.,., + +# reduce 43 omitted + +module_eval(<<'.,.,', 'parser.y', 155) + def _reduce_44(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| @grammar.add_type(id: id, tag: hash[:tag]) @@ -1473,8 +1536,8 @@ def _reduce_39(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 143) - def _reduce_40(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 163) + def _reduce_45(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1487,8 +1550,8 @@ def _reduce_40(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 153) - def _reduce_41(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 173) + def _reduce_46(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1501,8 +1564,8 @@ def _reduce_41(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 163) - def _reduce_42(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 183) + def _reduce_47(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1515,8 +1578,8 @@ def _reduce_42(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 173) - def _reduce_43(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 193) + def _reduce_48(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1529,8 +1592,8 @@ def _reduce_43(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 184) - def _reduce_44(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 204) + def _reduce_49(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) } @@ -1539,8 +1602,8 @@ def _reduce_44(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 190) - def _reduce_45(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 210) + def _reduce_50(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) } @@ -1549,8 +1612,8 @@ def _reduce_45(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 196) - def _reduce_46(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 216) + def _reduce_51(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) } @@ -1559,29 +1622,29 @@ def _reduce_46(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 201) - def _reduce_47(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 221) + def _reduce_52(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 202) - def _reduce_48(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 222) + def _reduce_53(val, _values, result) result = val[0].append(val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 204) - def _reduce_49(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 224) + def _reduce_54(val, _values, result) result = val result end .,., -module_eval(<<'.,.,', 'parser.y', 208) - def _reduce_50(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 228) + def _reduce_55(val, _values, result) rule = Grammar::ParameterizingRule::Rule.new(val[1].s_value, val[3], val[6]) @grammar.add_parameterizing_rule(rule) @@ -1589,22 +1652,22 @@ def _reduce_50(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 212) - def _reduce_51(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 232) + def _reduce_56(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 213) - def _reduce_52(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 233) + def _reduce_57(val, _values, result) result = val[0].append(val[2]) result end .,., -module_eval(<<'.,.,', 'parser.y', 217) - def _reduce_53(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 237) + def _reduce_58(val, _values, result) builder = val[0] result = [builder] @@ -1612,8 +1675,8 @@ def _reduce_53(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 222) - def _reduce_54(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 242) + def _reduce_59(val, _values, result) builder = val[2] result = val[0].append(builder) @@ -1621,8 +1684,8 @@ def _reduce_54(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 228) - def _reduce_55(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 248) + def _reduce_60(val, _values, result) reset_precs result = Grammar::ParameterizingRule::Rhs.new @@ -1630,8 +1693,8 @@ def _reduce_55(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 233) - def _reduce_56(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 253) + def _reduce_61(val, _values, result) reset_precs result = Grammar::ParameterizingRule::Rhs.new @@ -1639,8 +1702,8 @@ def _reduce_56(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 238) - def _reduce_57(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 258) + def _reduce_62(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1651,8 +1714,8 @@ def _reduce_57(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 246) - def _reduce_58(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 266) + def _reduce_63(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 @@ -1661,8 +1724,8 @@ def _reduce_58(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 252) - def _reduce_59(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 272) + def _reduce_64(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 @@ -1671,8 +1734,8 @@ def _reduce_59(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 258) - def _reduce_60(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 278) + def _reduce_65(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1683,16 +1746,16 @@ def _reduce_60(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 266) - def _reduce_61(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 286) + def _reduce_66(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 270) - def _reduce_62(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 290) + def _reduce_67(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -1703,8 +1766,8 @@ def _reduce_62(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 278) - def _reduce_63(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 298) + def _reduce_68(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -1715,168 +1778,168 @@ def _reduce_63(val, _values, result) end .,., -# reduce 64 omitted +# reduce 69 omitted -# reduce 65 omitted +# reduce 70 omitted -# reduce 66 omitted +# reduce 71 omitted -# reduce 67 omitted +# reduce 72 omitted -module_eval(<<'.,.,', 'parser.y', 293) - def _reduce_68(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 313) + def _reduce_73(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 297) - def _reduce_69(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 317) + def _reduce_74(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 301) - def _reduce_70(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 321) + def _reduce_75(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 304) - def _reduce_71(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 324) + def _reduce_76(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 305) - def _reduce_72(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 325) + def _reduce_77(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 73 omitted +# reduce 78 omitted -# reduce 74 omitted +# reduce 79 omitted -module_eval(<<'.,.,', 'parser.y', 312) - def _reduce_75(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 332) + def _reduce_80(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 316) - def _reduce_76(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 336) + def _reduce_81(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 320) - def _reduce_77(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 340) + def _reduce_82(val, _values, result) result = val[0].append(val[3]) result end .,., -module_eval(<<'.,.,', 'parser.y', 324) - def _reduce_78(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 344) + def _reduce_83(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 328) - def _reduce_79(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 348) + def _reduce_84(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 332) - def _reduce_80(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 352) + def _reduce_85(val, _values, result) result = [val[2]] result end .,., -module_eval(<<'.,.,', 'parser.y', 337) - def _reduce_81(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 357) + def _reduce_86(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 341) - def _reduce_82(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 361) + def _reduce_87(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 345) - def _reduce_83(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 365) + def _reduce_88(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 348) - def _reduce_84(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 368) + def _reduce_89(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 349) - def _reduce_85(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 369) + def _reduce_90(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 86 omitted +# reduce 91 omitted -module_eval(<<'.,.,', 'parser.y', 353) - def _reduce_87(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 373) + def _reduce_92(val, _values, result) on_action_error("ident after %prec", val[0]) if @prec_seen result end .,., -module_eval(<<'.,.,', 'parser.y', 354) - def _reduce_88(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 374) + def _reduce_93(val, _values, result) on_action_error("char after %prec", val[0]) if @prec_seen result end .,., -# reduce 89 omitted +# reduce 94 omitted -# reduce 90 omitted +# reduce 95 omitted -# reduce 91 omitted +# reduce 96 omitted -# reduce 92 omitted +# reduce 97 omitted -module_eval(<<'.,.,', 'parser.y', 364) - def _reduce_93(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 384) + def _reduce_98(val, _values, result) lhs = val[0] lhs.alias_name = val[1] val[3].each do |builder| @@ -1889,8 +1952,8 @@ def _reduce_93(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 375) - def _reduce_94(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 395) + def _reduce_99(val, _values, result) builder = val[0] if !builder.line builder.line = @lexer.line - 1 @@ -1901,8 +1964,8 @@ def _reduce_94(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 383) - def _reduce_95(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 403) + def _reduce_100(val, _values, result) builder = val[2] if !builder.line builder.line = @lexer.line - 1 @@ -1913,10 +1976,10 @@ def _reduce_95(val, _values, result) end .,., -# reduce 96 omitted +# reduce 101 omitted -module_eval(<<'.,.,', 'parser.y', 393) - def _reduce_97(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 413) + def _reduce_102(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1924,8 +1987,8 @@ def _reduce_97(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 398) - def _reduce_98(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 418) + def _reduce_103(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1933,8 +1996,8 @@ def _reduce_98(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 403) - def _reduce_99(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 423) + def _reduce_104(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1945,8 +2008,8 @@ def _reduce_99(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 411) - def _reduce_100(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 431) + def _reduce_105(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]], lhs_tag: val[3]) builder = val[0] builder.add_rhs(token) @@ -1957,8 +2020,8 @@ def _reduce_100(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 419) - def _reduce_101(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 439) + def _reduce_106(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3], lhs_tag: val[5]) builder = val[0] builder.add_rhs(token) @@ -1969,8 +2032,8 @@ def _reduce_101(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 427) - def _reduce_102(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 447) + def _reduce_107(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1981,16 +2044,16 @@ def _reduce_102(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 435) - def _reduce_103(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 455) + def _reduce_108(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 439) - def _reduce_104(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 459) + def _reduce_109(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -2001,8 +2064,8 @@ def _reduce_104(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 447) - def _reduce_105(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 467) + def _reduce_110(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -2013,70 +2076,70 @@ def _reduce_105(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 454) - def _reduce_106(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 474) + def _reduce_111(val, _values, result) result = "option" result end .,., -module_eval(<<'.,.,', 'parser.y', 455) - def _reduce_107(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 475) + def _reduce_112(val, _values, result) result = "nonempty_list" result end .,., -module_eval(<<'.,.,', 'parser.y', 456) - def _reduce_108(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 476) + def _reduce_113(val, _values, result) result = "list" result end .,., -module_eval(<<'.,.,', 'parser.y', 458) - def _reduce_109(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 478) + def _reduce_114(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 459) - def _reduce_110(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 479) + def _reduce_115(val, _values, result) result = val[0].append(val[2]) result end .,., -module_eval(<<'.,.,', 'parser.y', 460) - def _reduce_111(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 480) + def _reduce_116(val, _values, result) result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] result end .,., -module_eval(<<'.,.,', 'parser.y', 461) - def _reduce_112(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 481) + def _reduce_117(val, _values, result) result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[0].s_value, location: @lexer.location, args: val[2])] result end .,., -# reduce 113 omitted +# reduce 118 omitted -module_eval(<<'.,.,', 'parser.y', 464) - def _reduce_114(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 484) + def _reduce_119(val, _values, result) result = val[1].s_value result end .,., -# reduce 115 omitted +# reduce 120 omitted -# reduce 116 omitted +# reduce 121 omitted -module_eval(<<'.,.,', 'parser.y', 471) - def _reduce_117(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 491) + def _reduce_122(val, _values, result) begin_c_declaration('\Z') @grammar.epilogue_first_lineno = @lexer.line + 1 @@ -2084,8 +2147,8 @@ def _reduce_117(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 476) - def _reduce_118(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 496) + def _reduce_123(val, _values, result) end_c_declaration @grammar.epilogue = val[2].s_value @@ -2093,44 +2156,44 @@ def _reduce_118(val, _values, result) end .,., -# reduce 119 omitted +# reduce 124 omitted -# reduce 120 omitted +# reduce 125 omitted -# reduce 121 omitted +# reduce 126 omitted -# reduce 122 omitted +# reduce 127 omitted -# reduce 123 omitted +# reduce 128 omitted -module_eval(<<'.,.,', 'parser.y', 487) - def _reduce_124(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 507) + def _reduce_129(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 488) - def _reduce_125(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 508) + def _reduce_130(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 126 omitted +# reduce 131 omitted -# reduce 127 omitted +# reduce 132 omitted -module_eval(<<'.,.,', 'parser.y', 493) - def _reduce_128(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 513) + def _reduce_133(val, _values, result) result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) result end .,., -# reduce 129 omitted +# reduce 134 omitted -# reduce 130 omitted +# reduce 135 omitted def _reduce_none(val, _values, result) val[0] diff --git a/parser.y b/parser.y index f5b9f402..1aedc75e 100644 --- a/parser.y +++ b/parser.y @@ -129,6 +129,26 @@ rule lineno: val[3].line ) } + | "%after-shift" IDENTIFIER + { + @grammar.after_shift = val[1] + } + | "%before-reduce" IDENTIFIER + { + @grammar.before_reduce = val[1] + } + | "%after-reduce" IDENTIFIER + { + @grammar.after_reduce = val[1] + } + | "%after-shift-error-token" IDENTIFIER + { + @grammar.after_shift_error_token = val[1] + } + | "%after-pop-stack" IDENTIFIER + { + @grammar.after_pop_stack = val[1] + } symbol_declaration: "%token" token_declarations | "%type" symbol_declarations diff --git a/spec/fixtures/integration/after_shift.l b/spec/fixtures/integration/after_shift.l new file mode 100644 index 00000000..0ab1cc95 --- /dev/null +++ b/spec/fixtures/integration/after_shift.l @@ -0,0 +1,40 @@ +%option noinput nounput noyywrap never-interactive bison-bridge bison-locations + +%{ + +#include +#include +#include "after_shift.h" + +%} + +NUMBER [0-9]+ + +%% + +{NUMBER} { + ((void) yylloc); + yylval->val = atoi(yytext); + return NUM; +} + +[+\-\*\/\(\)] { + return yytext[0]; +} + +[\n|\r\n] { + return(YYEOF); +} + +[[:space:]] {} + +<> { + return(YYEOF); +} + +. { + fprintf(stderr, "Illegal character '%s'\n", yytext); + return(YYEOF); +} + +%% diff --git a/spec/fixtures/integration/after_shift.y b/spec/fixtures/integration/after_shift.y new file mode 100644 index 00000000..56ba9055 --- /dev/null +++ b/spec/fixtures/integration/after_shift.y @@ -0,0 +1,111 @@ +%{ + +#include +#include "after_shift.h" +#include "after_shift-lexer.h" + +static int yyerror(YYLTYPE *loc, const char *str); + +static void +after_shift(void) +{ + printf("after-shift: %d\n", __LINE__); +} + +static void +before_reduce(int len) +{ + printf("before-reduce: %d, %d\n", __LINE__, len); +} + +static void +after_reduce(int len) +{ + printf("after-reduce: %d, %d\n", __LINE__, len); +} + +static void +after_shift_error_token(void) +{ + printf("after-shift-error-token: %d\n", __LINE__); +} + +static void +after_pop_stack(int len) +{ + printf("after-pop-stack: %d, %d\n", __LINE__, len); +} + +%} + +%union { + int val; +} + +%after-shift after_shift +%before-reduce before_reduce +%after-reduce after_reduce +%after-shift-error-token after_shift_error_token +%after-pop-stack after_pop_stack + +%token NUM +%type expr +%left '+' '-' +%left '*' '/' + +%% + +program : /* empty */ + | expr { printf("=> %d\n", $1); } + | error + { + printf("error (%d)\n", $:1); + } + ; + +expr : NUM + | expr '+' expr + { + $$ = $1 + $3; + printf("+ (%d, %d, %d)\n", $:1, $:2, $:3); + } + | expr '-' expr + { + $$ = $1 - $3; + printf("- (%d, %d, %d)\n", $:1, $:2, $:3); + } + | expr '*' expr + { + $$ = $1 * $3; + printf("* (%d, %d, %d)\n", $:1, $:2, $:3); + } + | expr '/' expr + { + $$ = $1 / $3; + printf("/ (%d, %d, %d)\n", $:1, $:2, $:3); + } + | '(' expr ')' + { + $$ = $2; + printf("(...) (%d, %d, %d)\n", $:1, $:2, $:3); + } + ; + +%% + +static int yyerror(YYLTYPE *loc, const char *str) { + fprintf(stderr, "parse error: %s\n", str); + return 0; +} + +int main(int argc, char *argv[]) { + if (argc == 2) { + yy_scan_string(argv[1]); + } + + if (yyparse()) { + fprintf(stderr, "syntax error\n"); + return 1; + } + return 0; +} diff --git a/spec/lrama/grammar/code_spec.rb b/spec/lrama/grammar/code_spec.rb index 550791b9..dfd35ba7 100644 --- a/spec/lrama/grammar/code_spec.rb +++ b/spec/lrama/grammar/code_spec.rb @@ -2,8 +2,10 @@ let(:token_class) { Lrama::Lexer::Token } let(:user_code_dollar_dollar) { token_class::UserCode.new(s_value: 'print($$);') } let(:user_code_at_dollar) { token_class::UserCode.new(s_value: 'print(@$);') } + let(:user_code_index_dollar) { token_class::UserCode.new(s_value: 'print($:$);') } let(:user_code_dollar_n) { token_class::UserCode.new(s_value: 'print($n);') } let(:user_code_at_n) { token_class::UserCode.new(s_value: 'print(@n);') } + let(:user_code_index_n) { token_class::UserCode.new(s_value: 'print($:1);') } describe Lrama::Grammar::Code::InitialActionCode do describe "#translated_code" do @@ -17,6 +19,11 @@ expect(code.translated_code).to eq("print(yylloc);") end + it "raises error for '$:$'" do + code = described_class.new(type: :initial_action, token_code: user_code_index_dollar) + expect { code.translated_code }.to raise_error("$:$ can not be used in initial_action.") + end + it "raises error for '$n'" do code = described_class.new(type: :initial_action, token_code: user_code_dollar_n) expect { code.translated_code }.to raise_error("$n can not be used in initial_action.") @@ -26,6 +33,11 @@ code = described_class.new(type: :initial_action, token_code: user_code_at_n) expect { code.translated_code }.to raise_error("@n can not be used in initial_action.") end + + it "raises error for '$:n'" do + code = described_class.new(type: :initial_action, token_code: user_code_index_n) + expect { code.translated_code }.to raise_error("$:1 can not be used in initial_action.") + end end end @@ -41,6 +53,11 @@ expect { code.translated_code }.to raise_error("@$ can not be used in union.") end + it "raises error for '$:$'" do + code = described_class.new(type: :union, token_code: user_code_index_dollar) + expect { code.translated_code }.to raise_error("$:$ can not be used in union.") + end + it "raises error for '$n'" do code = described_class.new(type: :union, token_code: user_code_dollar_n) expect { code.translated_code }.to raise_error("$n can not be used in union.") @@ -50,6 +67,11 @@ code = described_class.new(type: :union, token_code: user_code_at_n) expect { code.translated_code }.to raise_error("@n can not be used in union.") end + + it "raises error for '$:n'" do + code = described_class.new(type: :union, token_code: user_code_index_n) + expect { code.translated_code }.to raise_error("$:1 can not be used in union.") + end end end @@ -67,6 +89,11 @@ expect(code.translated_code).to eq("print((*yylocationp));") end + it "raises error for '$:$'" do + code = described_class.new(type: :printer, token_code: user_code_index_dollar, tag: tag) + expect { code.translated_code }.to raise_error("$:$ can not be used in printer.") + end + it "raises error for '$n'" do code = described_class.new(type: :printer, token_code: user_code_dollar_n, tag: tag) expect { code.translated_code }.to raise_error("$n can not be used in printer.") @@ -76,6 +103,11 @@ code = described_class.new(type: :printer, token_code: user_code_at_n, tag: tag) expect { code.translated_code }.to raise_error("@n can not be used in printer.") end + + it "raises error for '$:n'" do + code = described_class.new(type: :printer, token_code: user_code_index_n, tag: tag) + expect { code.translated_code }.to raise_error("$:1 can not be used in printer.") + end end end @@ -120,6 +152,10 @@ | rule6 | rule7 | rule8 + | rule9 + | rule10 + | rule11 + | rule12 ; rule1: expr '+' expr { $$ = 0; } @@ -146,6 +182,17 @@ rule8: expr { $$ = $1 } '+' expr { $2; } ; + rule9: expr '+' expr { $:1; $:2; $:3; } + ; + + rule10: expr '+' expr { $:$; } + ; + + rule11: expr { $:1; } '+' expr { $:1; $:2; $:3; $:4; } + ; + + rule12: expr '+' expr[expr-right] { $:1; $:2; $:[expr-right]; } + ; %% GRAMMAR end @@ -212,6 +259,26 @@ expect { code.translated_code }.to raise_error("Tag is not specified for '$2' in 'rule8 -> expr, @3, '+', expr'") end end + + context "$: is used" do + it "translats '$:$' to '-yylen' and '$:n' to index from the last of array" do + code = grammar.rules.find {|r| r.lhs.id.s_value == "rule9" } + expect(code.translated_code).to eq(" (-2 - 1); (-1 - 1); (0 - 1); ") + + code = grammar.rules.find {|r| r.lhs.id.s_value == "rule10" } + expect { code.translated_code }.to raise_error("$:$ is not supported") + + # midrule action in rule11 + code = grammar.rules.find {|r| r.lhs.id.s_value == "@4" } + expect(code.translated_code).to eq(" (0 - 1); ") + + code = grammar.rules.find {|r| r.lhs.id.s_value == "rule11" } + expect(code.translated_code).to eq(" (-3 - 1); (-2 - 1); (-1 - 1); (0 - 1); ") + + code = grammar.rules.find {|r| r.lhs.id.s_value == "rule12" } + expect(code.translated_code).to eq(" (-2 - 1); (-1 - 1); (0 - 1); ") + end + end end end end diff --git a/spec/lrama/integration_spec.rb b/spec/lrama/integration_spec.rb index c3d0a142..de1ead2a 100644 --- a/spec/lrama/integration_spec.rb +++ b/spec/lrama/integration_spec.rb @@ -143,6 +143,67 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: []) end end + describe "after_shift, before_reduce & after_reduce" do + it "returns 9 for '(1+2)*3'" do + expected = <<~STR + after-shift: 12 + after-shift: 12 + before-reduce: 18, 1 + after-reduce: 24, 1 + after-shift: 12 + after-shift: 12 + before-reduce: 18, 1 + after-reduce: 24, 1 + before-reduce: 18, 3 + + (-3, -2, -1) + after-reduce: 24, 3 + after-shift: 12 + before-reduce: 18, 3 + (...) (-3, -2, -1) + after-reduce: 24, 3 + after-shift: 12 + after-shift: 12 + before-reduce: 18, 1 + after-reduce: 24, 1 + before-reduce: 18, 3 + * (-3, -2, -1) + after-reduce: 24, 3 + before-reduce: 18, 1 + => 9 + after-reduce: 24, 1 + after-shift: 12 + STR + + test_parser("after_shift", "( 1 + 2 ) * 3", expected) + + expected = <<~STR + after-shift: 12 + before-reduce: 18, 1 + after-reduce: 24, 1 + after-shift: 12 + after-pop-stack: 36, 1 + after-pop-stack: 36, 1 + after-shift-error-token: 30 + before-reduce: 18, 1 + error (-1) + after-reduce: 24, 1 + after-pop-stack: 36, 1 + after-shift-error-token: 30 + before-reduce: 18, 1 + error (-1) + after-reduce: 24, 1 + after-pop-stack: 36, 1 + after-shift-error-token: 30 + before-reduce: 18, 1 + error (-1) + after-reduce: 24, 1 + after-shift: 12 + STR + + test_parser("after_shift", "1 * + 2", expected) + end + end + # TODO: Add test case for "(1+2" describe "error_recovery" do it "returns 101 for '(1+)'" do diff --git a/template/bison/yacc.c b/template/bison/yacc.c index f72d3461..6145a950 100644 --- a/template/bison/yacc.c +++ b/template/bison/yacc.c @@ -1752,6 +1752,7 @@ YYLTYPE yylloc = yyloc_default; *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; +<%= output.after_shift_function("/* %after-shift code. */") %> /* Discard the shifted token. */ yychar = YYEMPTY; @@ -1784,6 +1785,7 @@ YYLTYPE yylloc = yyloc_default; unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; +<%= output.before_reduce_function("/* %before-reduce function. */") %> /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); @@ -1809,6 +1811,7 @@ YYLTYPE yylloc = yyloc_default; YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc<%= output.user_args %>); YYPOPSTACK (yylen); +<%= output.after_reduce_function("/* %after-reduce function. */") %> yylen = 0; *++yyvsp = yyval; @@ -1910,6 +1913,7 @@ YYLTYPE yylloc = yyloc_default; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); +<%= output.after_pop_stack_function("yylen", "/* %after-pop-stack function. */") %> yylen = 0; YY_STACK_PRINT (yyss, yyssp<%= output.user_args %>); yystate = *yyssp; @@ -1969,6 +1973,7 @@ YYLTYPE yylloc = yyloc_default; yydestruct ("Error: popping", YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp<%= output.user_args %>); YYPOPSTACK (1); +<%= output.after_pop_stack_function(1, "/* %after-pop-stack function. */") %> yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp<%= output.user_args %>); } @@ -1983,6 +1988,7 @@ YYLTYPE yylloc = yyloc_default; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp<%= output.user_args %>); +<%= output.after_shift_error_token_function("/* %after-shift-error-token code. */") %> yystate = yyn; goto yynewstate;