Skip to content

Commit

Permalink
Merge pull request ruby#485 from ydah/nterm-support
Browse files Browse the repository at this point in the history
Add support for %type declarations using `%nterm` in Nonterminal Symbols
  • Loading branch information
ydah authored Dec 22, 2024
2 parents 84eb007 + 54333a7 commit e606e44
Show file tree
Hide file tree
Showing 8 changed files with 498 additions and 433 deletions.
2 changes: 1 addition & 1 deletion lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Grammar
:after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
:symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations

def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term, :find_term_by_s_value,
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
:find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
:fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!
Expand Down
4 changes: 4 additions & 0 deletions lib/lrama/grammar/symbols/resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ def add_nterm(id:, alias_name: nil, tag: nil)
nterm
end

def find_term_by_s_value(s_value)
terms.find { |s| s.id.s_value == s_value }
end

def find_symbol_by_s_value(s_value)
symbols.find { |s| s.id.s_value == s_value }
end
Expand Down
1 change: 1 addition & 0 deletions lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Lexer
%union
%token
%type
%nterm
%left
%right
%nonassoc
Expand Down
879 changes: 450 additions & 429 deletions lib/lrama/parser.rb

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ rule
}
}
}
| "%nterm" symbol_declarations
{
val[1].each {|hash|
hash[:tokens].each {|id|
if @grammar.find_term_by_s_value(id.s_value)
on_action_error("symbol #{id.s_value} redeclared as a nonterminal", id)
else
@grammar.add_type(id: id, tag: hash[:tag])
end
}
}
}
| "%left" token_declarations_for_precedence
{
val[1].each {|hash|
Expand Down
1 change: 1 addition & 0 deletions spec/lrama/diagnostics_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
%token tEQEQ "=="
%type <i> class /* comment for class */
%nterm <str> string /* comment for string */
%nonassoc tEQEQ
%left tPLUS tMINUS '>'
Expand Down
6 changes: 3 additions & 3 deletions spec/lrama/grammar/code_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@
%type <rule2> rule2
%type <rule3> rule3
%type <rule4> rule4
%type <rule5> rule5
%type <rule6> rule6
%type <rule7> rule7
%nterm <rule5> rule5
%nterm <rule6> rule6
%nterm <rule7> rule7
%%
Expand Down
26 changes: 26 additions & 0 deletions spec/lrama/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3710,6 +3710,32 @@ class : keyword_class tSTRING keyword_end { code 1 }
ERROR
end
end

context "when pass the terminal symbol to `%nterm`" do
it "raises an error" do
y = <<~INPUT
%{
// Prologue
%}
%token EOI 0 "EOI"
%nterm EOI
%%
program: /* empty */
;
INPUT

parser = Lrama::Parser.new(y, "error_messages/parse.y")

expect { parser.parse }.to raise_error(ParseError, <<~ERROR)
error_messages/parse.y:6:7: symbol EOI redeclared as a nonterminal
%nterm EOI
^^^
ERROR
end
end
end
end

Expand Down

0 comments on commit e606e44

Please sign in to comment.