diff --git a/lib/lrama/grammar/reference.rb b/lib/lrama/grammar/reference.rb index 24c98129..c56e7673 100644 --- a/lib/lrama/grammar/reference.rb +++ b/lib/lrama/grammar/reference.rb @@ -2,11 +2,12 @@ module Lrama class Grammar # type: :dollar or :at # name: String (e.g. $$, $foo, $expr.right) - # index: Integer (e.g. $1) + # number: Integer (e.g. $1) + # index: Integer # ex_tag: "$1" (Optional) - class Reference < Struct.new(:type, :name, :index, :ex_tag, :first_column, :last_column, keyword_init: true) + class Reference < Struct.new(:type, :name, :number, :index, :ex_tag, :first_column, :last_column, keyword_init: true) def value - name || index + name || number end end end diff --git a/lib/lrama/grammar/rule_builder.rb b/lib/lrama/grammar/rule_builder.rb index 954bb0d5..3cbaab5b 100644 --- a/lib/lrama/grammar/rule_builder.rb +++ b/lib/lrama/grammar/rule_builder.rb @@ -181,11 +181,18 @@ def numberize_references if referring_symbol[1] == 0 # Refers to LHS ref.name = '$' else - ref.index = referring_symbol[1] + ref.number = referring_symbol[1] end end end + if ref.number + # TODO: When Inlining is implemented, for example, if `$1` is expanded to multiple RHS tokens, + # `$2` needs to access `$2 + n` to actually access it. So, after the Inlining implementation, + # it needs resolves from number to index. + ref.index = ref.number + end + # TODO: Need to check index of @ too? next if ref.type == :at diff --git a/lib/lrama/lexer/token/user_code.rb b/lib/lrama/lexer/token/user_code.rb index 765ca2fb..1c0376c8 100644 --- a/lib/lrama/lexer/token/user_code.rb +++ b/lib/lrama/lexer/token/user_code.rb @@ -38,7 +38,7 @@ def scan_reference(scanner) return Lrama::Grammar::Reference.new(type: :dollar, name: "$", ex_tag: tag, first_column: start, last_column: scanner.pos) when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $1 tag = scanner[1] ? Lrama::Lexer::Token::Tag.new(s_value: scanner[1]) : nil - return Lrama::Grammar::Reference.new(type: :dollar, index: Integer(scanner[2]), ex_tag: tag, first_column: start, last_column: scanner.pos) + return Lrama::Grammar::Reference.new(type: :dollar, number: Integer(scanner[2]), index: Integer(scanner[2]), ex_tag: tag, first_column: start, last_column: scanner.pos) when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $program (named reference without brackets) tag = scanner[1] ? Lrama::Lexer::Token::Tag.new(s_value: scanner[1]) : nil return Lrama::Grammar::Reference.new(type: :dollar, name: scanner[2], ex_tag: tag, first_column: start, last_column: scanner.pos) @@ -51,7 +51,7 @@ def scan_reference(scanner) when scanner.scan(/@\$/) # @$ return Lrama::Grammar::Reference.new(type: :at, name: "$", first_column: start, last_column: scanner.pos) when scanner.scan(/@(\d+)/) # @1 - return Lrama::Grammar::Reference.new(type: :at, index: Integer(scanner[1]), first_column: start, last_column: scanner.pos) + return Lrama::Grammar::Reference.new(type: :at, number: Integer(scanner[1]), 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: :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) diff --git a/sig/lrama/grammar/reference.rbs b/sig/lrama/grammar/reference.rbs index e1b781d7..a27cbac9 100644 --- a/sig/lrama/grammar/reference.rbs +++ b/sig/lrama/grammar/reference.rbs @@ -3,6 +3,7 @@ module Lrama class Reference attr_accessor type: ::Symbol attr_accessor name: String + attr_accessor number: Integer attr_accessor index: Integer attr_accessor ex_tag: Lexer::Token? attr_accessor first_column: Integer @@ -10,7 +11,7 @@ module Lrama attr_accessor position_in_rhs: Integer? def initialize: ( - type: ::Symbol, ?name: String, ?index: Integer, ?ex_tag: Lexer::Token?, + type: ::Symbol, ?name: String, ?number: Integer, ?index: Integer, ?ex_tag: Lexer::Token?, first_column: Integer, last_column: Integer, ?position_in_rhs: Integer? ) -> void diff --git a/spec/lrama/lexer/token/user_code_spec.rb b/spec/lrama/lexer/token/user_code_spec.rb index 826149bd..9311644f 100644 --- a/spec/lrama/lexer/token/user_code_spec.rb +++ b/spec/lrama/lexer/token/user_code_spec.rb @@ -15,10 +15,10 @@ # $1 references = Lrama::Lexer::Token::UserCode.new(s_value: " $1 ", location: location).references expect(references.count).to eq 1 - expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :dollar, index: 1, ex_tag: nil, first_column: 1, last_column: 3) + expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :dollar, number: 1, index: 1, ex_tag: nil, first_column: 1, last_column: 3) references = Lrama::Lexer::Token::UserCode.new(s_value: " $1 ", location: location).references expect(references.count).to eq 1 - expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :dollar, index: 1, ex_tag: Lrama::Lexer::Token::Tag.new(s_value: ""), first_column: 1, last_column: 9) + expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :dollar, number: 1, index: 1, ex_tag: Lrama::Lexer::Token::Tag.new(s_value: ""), first_column: 1, last_column: 9) # $foo references = Lrama::Lexer::Token::UserCode.new(s_value: " $foo ", location: location).references @@ -44,7 +44,7 @@ # @1 references = Lrama::Lexer::Token::UserCode.new(s_value: " @1 ", location: location).references expect(references.count).to eq 1 - expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :at, index: 1, ex_tag: nil, first_column: 1, last_column: 3) + expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :at, number: 1, index: 1, ex_tag: nil, first_column: 1, last_column: 3) # @foo references = Lrama::Lexer::Token::UserCode.new(s_value: " @foo ", location: location).references