Skip to content

Commit 231a8c5

Browse files
committed
Support parameterized rule's arguments include inline
Support following: ``` %rule %inline op : '+' | '-' ; %% operation : op? ; ```
1 parent d6205d4 commit 231a8c5

File tree

4 files changed

+124
-1
lines changed

4 files changed

+124
-1
lines changed

lib/lrama/grammar/rule_builder.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def complete_input
5656
def setup_rules
5757
preprocess_references unless @skip_preprocess_references
5858
process_rhs
59+
resolve_inline_rules
5960
build_rules
6061
end
6162

@@ -79,6 +80,7 @@ def preprocess_references
7980

8081
def build_rules
8182
tokens = @replaced_rhs
83+
return if tokens.any? { |t| @parameterized_resolver.find_inline(t) }
8284

8385
rule = Rule.new(
8486
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
@@ -152,6 +154,20 @@ def process_rhs
152154
end
153155
end
154156

157+
def resolve_inline_rules
158+
while @rule_builders_for_parameterized.any?(&:has_inline_rules?) do
159+
@rule_builders_for_parameterized = @rule_builders_for_parameterized.flat_map do |rule_builder|
160+
if rule_builder.has_inline_rules?
161+
inlined_builders = Inline::Resolver.new(rule_builder).resolve
162+
inlined_builders.each { |builder| builder.setup_rules }
163+
inlined_builders
164+
else
165+
rule_builder
166+
end
167+
end
168+
end
169+
end
170+
155171
def numberize_references
156172
# Bison n'th component is 1-origin
157173
(rhs + [user_code]).compact.each.with_index(1) do |token, i|

sig/lrama/grammar/rule_builder.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ module Lrama
2424
def initialize: (Counter rule_counter, Counter midrule_action_counter, Grammar::Parameterized::Resolver parameterized_resolver, ?Integer position_in_original_rule_rhs, ?lhs_tag: Lexer::Token::Tag?, ?skip_preprocess_references: bool) -> void
2525
def add_rhs: (Lexer::Token rhs) -> void
2626
def has_inline_rules?: -> bool
27-
def resolve_inline_rules: -> Array[RuleBuilder]
2827
def user_code=: (Lexer::Token::UserCode? user_code) -> void
2928
def precedence_sym=: (Grammar::Symbol? precedence_sym) -> void
3029
def complete_input: () -> void
@@ -40,6 +39,7 @@ module Lrama
4039
def resolve_inline: () -> void
4140
def resolve_inline_rhs: (RuleBuilder rule_builder, Grammar::Parameterized::Rhs inline_rhs, Integer index, ?Binding bindings) -> void
4241
def replace_inline_user_code: (Grammar::Parameterized::Rhs inline_rhs, Integer index) -> Lexer::Token::UserCode?
42+
def resolve_inline_rules: () -> void
4343
def numberize_references: () -> void
4444
def flush_user_code: () -> void
4545
end
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This is comment for this file.
3+
*/
4+
5+
%{
6+
// Prologue
7+
static int yylex(YYSTYPE *val, YYLTYPE *loc);
8+
static int yyerror(YYLTYPE *loc, const char *str);
9+
%}
10+
11+
%union {
12+
int i;
13+
}
14+
15+
%rule %inline op : '+'
16+
| '-'
17+
;
18+
19+
%%
20+
21+
operation : op?
22+
;
23+
24+
%%
25+
26+
static int yylex(YYSTYPE *yylval, YYLTYPE *loc)
27+
{
28+
return 0;
29+
}
30+
31+
static int yyerror(YYLTYPE *loc, const char *str)
32+
{
33+
return 0;
34+
}
35+
36+
int main(int argc, char *argv[])
37+
{
38+
}

spec/lrama/parser_spec.rb

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,75 @@
26762676
end
26772677
end
26782678

2679+
context "when parameterized rule's arguments include inline" do
2680+
let(:path) { "inlining/parameterized_args_include_inline.y" }
2681+
2682+
it "expands inlining rules" do
2683+
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
2684+
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
2685+
Sym.new(id: T::Ident.new(s_value: "option_op"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: true),
2686+
Sym.new(id: T::Ident.new(s_value: "operation"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: true),
2687+
])
2688+
2689+
expect(grammar.rules).to eq([
2690+
Rule.new(
2691+
id: 0,
2692+
lhs: grammar.find_symbol_by_s_value!("$accept"),
2693+
rhs: [
2694+
grammar.find_symbol_by_s_value!("operation"),
2695+
grammar.find_symbol_by_s_value!("YYEOF"),
2696+
],
2697+
token_code: nil,
2698+
nullable: false,
2699+
precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"),
2700+
lineno: 21,
2701+
),
2702+
Rule.new(
2703+
id: 1,
2704+
lhs: grammar.find_symbol_by_s_value!("option_op"),
2705+
rhs: [],
2706+
token_code: nil,
2707+
nullable: true,
2708+
precedence_sym: nil,
2709+
lineno: 21,
2710+
),
2711+
Rule.new(
2712+
id: 2,
2713+
lhs: grammar.find_symbol_by_s_value!("option_op"),
2714+
rhs: [
2715+
grammar.find_symbol_by_s_value!("'+'"),
2716+
],
2717+
token_code: nil,
2718+
nullable: false,
2719+
precedence_sym: grammar.find_symbol_by_s_value!("'+'"),
2720+
lineno: 21,
2721+
),
2722+
Rule.new(
2723+
id: 3,
2724+
lhs: grammar.find_symbol_by_s_value!("option_op"),
2725+
rhs: [
2726+
grammar.find_symbol_by_s_value!("'-'"),
2727+
],
2728+
token_code: nil,
2729+
nullable: false,
2730+
precedence_sym: grammar.find_symbol_by_s_value!("'-'"),
2731+
lineno: 21,
2732+
),
2733+
Rule.new(
2734+
id: 4,
2735+
lhs: grammar.find_symbol_by_s_value!("operation"),
2736+
rhs: [
2737+
grammar.find_symbol_by_s_value!("option_op"),
2738+
],
2739+
token_code: nil,
2740+
nullable: true,
2741+
precedence_sym: nil,
2742+
lineno: 21,
2743+
),
2744+
])
2745+
end
2746+
end
2747+
26792748
context 'when inline with resolve index `@n` style' do
26802749
let(:path) { "inlining/resolve_index.y" }
26812750

0 commit comments

Comments
 (0)