Skip to content

Commit 2cb042d

Browse files
committed
wip
1 parent 95e0cc2 commit 2cb042d

File tree

12 files changed

+729
-425
lines changed

12 files changed

+729
-425
lines changed

lib/lrama/grammar.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Grammar
3030
:after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
3131
:symbols_resolver, :types,
3232
:rules, :rule_builders,
33-
:sym_to_rules, :no_stdlib
33+
:sym_to_rules, :no_stdlib, :if_count
3434

3535
def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
3636
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
@@ -58,6 +58,7 @@ def initialize(rule_counter)
5858
@accept_symbol = nil
5959
@aux = Auxiliary.new
6060
@no_stdlib = false
61+
@if_count = 0
6162

6263
append_special_symbols
6364
end
@@ -170,6 +171,10 @@ def find_rules_by_symbol(sym)
170171
@sym_to_rules[sym.number]
171172
end
172173

174+
def initialize_if_count
175+
@if_count = 0
176+
end
177+
173178
private
174179

175180
def compute_nullable

lib/lrama/grammar/binding.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ def initialize(parameterizing_rule, actual_args)
1212
end
1313

1414
def resolve_symbol(symbol)
15+
return unless symbol
16+
1517
if symbol.is_a?(Lexer::Token::InstantiateRule)
1618
resolved_args = symbol.args.map { |arg| resolve_symbol(arg) }
1719
Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag)
20+
elsif symbol.is_a?(Lexer::Token::ControlSyntax)
21+
resolved = symbol.dup
22+
resolved.condition = @parameter_to_arg[symbol.conditon_value]
23+
resolved
1824
else
1925
@parameter_to_arg[symbol.s_value] || symbol
2026
end

lib/lrama/grammar/parameterizing_rule/rhs.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def initialize
1010
@precedence_sym = nil
1111
end
1212

13+
def resolve_symbols(bindings)
14+
15+
end
16+
1317
def resolve_user_code(bindings)
1418
return unless user_code
1519

lib/lrama/grammar/rule_builder.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,14 @@ def process_rhs
133133
parameterizing_rule.rhs_list.each do |r|
134134
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: token.lhs_tag || parameterizing_rule.tag)
135135
rule_builder.lhs = lhs_token
136-
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
136+
last_sym = bindings.resolve_symbol(r.symbols.last)
137+
next if last_sym.is_a?(Lexer::Token::ControlSyntax) && last_sym.if? && last_sym.true?
138+
r.symbols.each do |sym|
139+
resolved = bindings.resolve_symbol(sym)
140+
unless resolved.is_a?(Lexer::Token::ControlSyntax)
141+
rule_builder.add_rhs(bindings.resolve_symbol(sym))
142+
end
143+
end
137144
rule_builder.line = line
138145
rule_builder.precedence_sym = r.precedence_sym
139146
rule_builder.user_code = r.resolve_user_code(bindings)

lib/lrama/lexer.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class Lexer
3838
%rule
3939
%no-stdlib
4040
%inline
41+
%if
42+
%endif
43+
%true
44+
%false
4145
)
4246

4347
def initialize(grammar_file)

lib/lrama/lexer/token.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
require 'lrama/lexer/token/bool'
12
require 'lrama/lexer/token/char'
3+
require 'lrama/lexer/token/control_syntax'
24
require 'lrama/lexer/token/ident'
35
require 'lrama/lexer/token/instantiate_rule'
46
require 'lrama/lexer/token/tag'

lib/lrama/lexer/token/bool.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module Lrama
2+
class Lexer
3+
class Token
4+
class Bool < Token
5+
end
6+
end
7+
end
8+
end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Lrama
2+
class Lexer
3+
class Token
4+
class ControlSyntax < Token
5+
attr_accessor :condition
6+
7+
def initialize(s_value:, location:, condition: nil)
8+
@condition = condition
9+
super(s_value: s_value, location: location)
10+
end
11+
12+
def if?
13+
s_value == '%if'
14+
end
15+
16+
def endif?
17+
s_value == '%endif'
18+
end
19+
20+
def true?
21+
@condition.s_value
22+
end
23+
24+
def conditon_value
25+
@condition&.s_value
26+
end
27+
end
28+
end
29+
end
30+
end

lib/lrama/parser.rb

Lines changed: 527 additions & 420 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser.y

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ rule
242242
{
243243
rule = Grammar::ParameterizingRule::Rule.new(val[2].s_value, [], val[4], is_inline: true)
244244
@grammar.add_parameterizing_rule(rule)
245+
@grammar.initialize_if_count
245246
}
246247

247248
rule_args: IDENTIFIER { result = [val[0]] }
@@ -282,7 +283,7 @@ rule
282283
builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]])
283284
result = builder
284285
}
285-
| rule_rhs IDENTIFIER "(" parameterizing_args ")" tag_opt
286+
| rule_rhs IDENTIFIER "(" parameterizing_rule_args ")" tag_opt
286287
{
287288
builder = val[0]
288289
builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3], lhs_tag: val[5])
@@ -316,6 +317,21 @@ rule
316317
builder.precedence_sym = sym
317318
result = builder
318319
}
320+
| rule_rhs "%if" "(" IDENTIFIER ")"
321+
{
322+
builder = val[0]
323+
builder.symbols << Lrama::Lexer::Token::ControlSyntax.new(s_value: val[1], location: @lexer.location, condition: val[3])
324+
@grammar.if_count += 1
325+
result = builder
326+
}
327+
| rule_rhs "%endif"
328+
{
329+
on_action_error("no %if before %endif", val[0]) if @grammar.if_count == 0
330+
builder = val[0]
331+
builder.symbols << Lrama::Lexer::Token::ControlSyntax.new(s_value: val[1], location: @lexer.location)
332+
@grammar.if_count -= 1
333+
result = builder
334+
}
319335

320336
int_opt: # empty
321337
| INTEGER
@@ -491,11 +507,22 @@ rule
491507
| "+" { result = "nonempty_list" }
492508
| "*" { result = "list" }
493509

494-
parameterizing_args: symbol { result = [val[0]] }
495-
| parameterizing_args ',' symbol { result = val[0].append(val[2]) }
510+
parameterizing_rule_args: symbol { result = [val[0]] }
511+
| parameterizing_args ',' symbol { result = val[0].append(val[2]) }
512+
| symbol parameterizing_suffix { result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] }
513+
| IDENTIFIER "(" parameterizing_args ")" { result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[0].s_value, location: @lexer.location, args: val[2])] }
514+
515+
parameterizing_args: symbol_or_bool { result = [val[0]] }
516+
| parameterizing_args ',' symbol_or_bool { result = val[0].append(val[2]) }
496517
| symbol parameterizing_suffix { result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] }
497518
| IDENTIFIER "(" parameterizing_args ")" { result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[0].s_value, location: @lexer.location, args: val[2])] }
498519

520+
symbol_or_bool: symbol
521+
| bool
522+
523+
bool: "%true" { result = Lrama::Lexer::Token::Bool.new(s_value: true) }
524+
| "%false" { result = Lrama::Lexer::Token::Bool.new(s_value: false) }
525+
499526
named_ref_opt: # empty
500527
| '[' IDENTIFIER ']' { result = val[1].s_value }
501528

0 commit comments

Comments
 (0)