Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/lrama/grammar/rule_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,12 @@ def numberize_references
ref.index = ref.number
end

# TODO: Need to check index of @ too?
next if ref.type == :at

if ref.index
# TODO: Prohibit $0 even so Bison allows it?
# See: https://www.gnu.org/software/bison/manual/html_node/Actions.html
token.invalid_ref(ref, "Can not refer following component. #{ref.index} >= #{i}.") if ref.index >= i
next if ref.type == :at

rhs[ref.index - 1].referred = true
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/integration/contains_at_reference.y
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static int yyerror(YYLTYPE *loc, const char *str);

%%

program : /* empty */ { (void)@1; }
program : /* empty */ { (void)@0; }
;

%%
Expand Down
35 changes: 35 additions & 0 deletions spec/lrama/grammar/rule_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,41 @@
end
end

context "location variables in mid action rule refer to following component" do
let(:text) { "class : keyword_class { @3; } tSTRING keyword_end { $class = $1; }" }
let(:grammar_file) { Lrama::Lexer::GrammarFile.new(path, text) }
let(:location_1) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 0, last_line: 1, last_column: 5) }
let(:location_2) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 8, last_line: 1, last_column: 21) }
let(:location_3) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 23, last_line: 1, last_column: 28) }
let(:location_4) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 30, last_line: 1, last_column: 37) }
let(:location_5) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 38, last_line: 1, last_column: 49) }
let(:location_6) { Lrama::Lexer::Location.new(grammar_file: grammar_file, first_line: 1, first_column: 51, last_line: 1, last_column: 65) }
let(:token_1) { Lrama::Lexer::Token::Ident.new(s_value: "class", location: location_1) }
let(:token_2) { Lrama::Lexer::Token::Ident.new(s_value: "keyword_class", location: location_2) }
let(:token_3) { Lrama::Lexer::Token::UserCode.new(s_value: " @3; ", location: location_3) }
let(:token_4) { Lrama::Lexer::Token::Ident.new(s_value: "tSTRING", location: location_4) }
let(:token_5) { Lrama::Lexer::Token::Ident.new(s_value: "keyword_end", location: location_5) }
let(:token_6) { Lrama::Lexer::Token::UserCode.new(s_value: " $class = $1; ", location: location_6) }

it "raises error" do
rule_builder.lhs = token_1
rule_builder.add_rhs(token_2)
rule_builder.user_code = token_3
rule_builder.add_rhs(token_4)
rule_builder.add_rhs(token_5)
rule_builder.user_code = token_6
rule_builder.complete_input

expected = <<~TEXT
parse.y:1:24: Can not refer following component. 3 >= 2.
1 | class : keyword_class { @3; } tSTRING keyword_end { $class = $1; }
| ^~
TEXT

expect { rule_builder.send(:preprocess_references) }.to raise_error(expected)
end
end

context "variables refer with wrong name" do
let(:text) { "class : keyword_class tSTRING keyword_end { $classes = $1; }" }
let(:grammar_file) { Lrama::Lexer::GrammarFile.new(path, text) }
Expand Down