lrama 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +20 -5
- data/Gemfile +1 -1
- data/NEWS.md +46 -0
- data/Steepfile +2 -3
- data/lib/lrama/command.rb +17 -3
- data/lib/lrama/context.rb +2 -22
- data/lib/lrama/grammar/binding.rb +24 -0
- data/lib/lrama/grammar/code/rule_action.rb +1 -1
- data/lib/lrama/grammar/parameterizing_rule/resolver.rb +39 -0
- data/lib/lrama/grammar/parameterizing_rule/rhs.rb +15 -0
- data/lib/lrama/grammar/parameterizing_rule/rule.rb +16 -0
- data/lib/lrama/grammar/parameterizing_rule.rb +3 -6
- data/lib/lrama/grammar/percent_code.rb +3 -3
- data/lib/lrama/grammar/rule_builder.rb +59 -25
- data/lib/lrama/grammar/type.rb +13 -1
- data/lib/lrama/grammar.rb +7 -9
- data/lib/lrama/lexer/grammar_file.rb +1 -1
- data/lib/lrama/lexer/token/instantiate_rule.rb +7 -2
- data/lib/lrama/lexer/token.rb +5 -0
- data/lib/lrama/lexer.rb +2 -7
- data/lib/lrama/output.rb +2 -2
- data/lib/lrama/parser.rb +166 -148
- data/lib/lrama/version.rb +1 -1
- data/parser.y +8 -8
- data/sig/lrama/grammar/binding.rbs +16 -0
- data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +21 -0
- data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +13 -0
- data/sig/lrama/grammar/parameterizing_rule/rule.rbs +14 -0
- data/sig/lrama/grammar/parameterizing_rule.rbs +0 -4
- data/sig/lrama/grammar/percent_code.rbs +3 -3
- data/sig/lrama/grammar/rule_builder.rbs +9 -6
- data/sig/lrama/lexer/token/instantiate_rule.rbs +4 -2
- data/sig/lrama/lexer/token.rbs +1 -0
- metadata +11 -9
- data/lib/lrama/grammar/parameterizing_rule_builder.rb +0 -34
- data/lib/lrama/grammar/parameterizing_rule_resolver.rb +0 -30
- data/lib/lrama/grammar/parameterizing_rule_rhs_builder.rb +0 -53
- data/sig/lrama/grammar/parameterizing_rule_builder.rbs +0 -19
- data/sig/lrama/grammar/parameterizing_rule_resolver.rbs +0 -16
- data/sig/lrama/grammar/parameterizing_rule_rhs_builder.rbs +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50dc10cc2d790e778dcb6a35b789f146e69157b3c99d5b66059d95c025546ea6
|
4
|
+
data.tar.gz: cbc16ede0db21b5d22f74c47dfd7a87af2ae20e15f72afc9ea8a79980531861d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7567e78e28cb912eb6dae8182827b5c6555924757bffe4fd9db81f79dd117aaf00f0918c90ead79d3567eeee802b90556540141fd5d4083bf5d6013c075cb20c
|
7
|
+
data.tar.gz: e58f803bc04114bdeb69b74a5e34ab9649241dafb9fe69a62f7d17ea87026411e3f743c54537fa092a9d6cea547a046fc762a78d9daebf92c3184be5502a24c1
|
data/.github/workflows/test.yaml
CHANGED
@@ -8,12 +8,19 @@ permissions:
|
|
8
8
|
contents: read
|
9
9
|
|
10
10
|
jobs:
|
11
|
+
ruby-versions:
|
12
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
13
|
+
with:
|
14
|
+
engine: cruby
|
15
|
+
min_version: 2.5
|
16
|
+
|
11
17
|
test:
|
18
|
+
needs: ruby-versions
|
12
19
|
runs-on: ubuntu-20.04
|
13
20
|
strategy:
|
14
21
|
fail-fast: false
|
15
22
|
matrix:
|
16
|
-
ruby:
|
23
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
17
24
|
steps:
|
18
25
|
- uses: actions/checkout@v4
|
19
26
|
- uses: ruby/setup-ruby@v1
|
@@ -29,14 +36,22 @@ jobs:
|
|
29
36
|
fail-fast: false
|
30
37
|
matrix:
|
31
38
|
ruby: ['head']
|
39
|
+
defaults:
|
40
|
+
run:
|
41
|
+
shell: msys2 {0}
|
32
42
|
steps:
|
33
43
|
- uses: actions/checkout@v4
|
34
44
|
- uses: ruby/setup-ruby@v1
|
35
45
|
with:
|
36
46
|
ruby-version: ${{ matrix.ruby }}
|
37
47
|
bundler-cache: true
|
38
|
-
-
|
39
|
-
|
48
|
+
- uses: msys2/setup-msys2@v2
|
49
|
+
id: setup-msys2
|
50
|
+
with:
|
51
|
+
update: true
|
52
|
+
install: >-
|
53
|
+
flex
|
54
|
+
- run: flex --help
|
40
55
|
- run: bundle install
|
41
56
|
- run: bundle exec rspec
|
42
57
|
test-memory:
|
@@ -118,12 +133,12 @@ jobs:
|
|
118
133
|
ruby-version: ${{ matrix.baseruby }}
|
119
134
|
bundler-cache: true
|
120
135
|
- run: git clone --depth=1 https://github.com/ruby/ruby.git -b ${{ matrix.ruby_branch }} ../ruby
|
121
|
-
working-directory:
|
136
|
+
working-directory: .
|
122
137
|
- run: mkdir -p tool/lrama
|
123
138
|
working-directory: ../ruby
|
124
139
|
- name: Copy Lrama to ruby/tool
|
125
140
|
run: cp -r LEGAL.md NEWS.md MIT exe lib template ../ruby/tool/lrama
|
126
|
-
working-directory:
|
141
|
+
working-directory: .
|
127
142
|
- run: tree tool/lrama
|
128
143
|
working-directory: ../ruby
|
129
144
|
# See also https://github.com/ruby/ruby/blob/master/.github/workflows/ubuntu.yml
|
data/Gemfile
CHANGED
@@ -12,6 +12,6 @@ gem "stackprof", platforms: [:ruby] # stackprof doesn't support Windows
|
|
12
12
|
# Recent steep requires Ruby >= 3.0.0.
|
13
13
|
# Then skip install on some CI jobs.
|
14
14
|
if !ENV['GITHUB_ACTION'] || ENV['INSTALL_STEEP'] == 'true'
|
15
|
-
gem "rbs", "3.4.
|
15
|
+
gem "rbs", "3.4.1", require: false
|
16
16
|
gem "steep", "1.6.0", require: false
|
17
17
|
end
|
data/NEWS.md
CHANGED
@@ -1,5 +1,49 @@
|
|
1
1
|
# NEWS for Lrama
|
2
2
|
|
3
|
+
## Lrama 0.6.1 (2024-01-13)
|
4
|
+
|
5
|
+
### Nested parameterizing rules
|
6
|
+
|
7
|
+
Allow to pass an instantiated rule to other parameterizing rules.
|
8
|
+
|
9
|
+
```
|
10
|
+
%rule constant(X) : X
|
11
|
+
;
|
12
|
+
|
13
|
+
%rule option(Y) : /* empty */
|
14
|
+
| Y
|
15
|
+
;
|
16
|
+
|
17
|
+
%%
|
18
|
+
|
19
|
+
program : option(constant(number)) // Nested rule
|
20
|
+
;
|
21
|
+
%%
|
22
|
+
```
|
23
|
+
|
24
|
+
Allow to use nested parameterizing rules when define parameterizing rules.
|
25
|
+
|
26
|
+
```
|
27
|
+
%rule option(x) : /* empty */
|
28
|
+
| X
|
29
|
+
;
|
30
|
+
|
31
|
+
%rule double(Y) : Y Y
|
32
|
+
;
|
33
|
+
|
34
|
+
%rule double_opt(A) : option(double(A)) // Nested rule
|
35
|
+
;
|
36
|
+
|
37
|
+
%%
|
38
|
+
|
39
|
+
program : double_opt(number)
|
40
|
+
;
|
41
|
+
|
42
|
+
%%
|
43
|
+
```
|
44
|
+
|
45
|
+
https://github.com/ruby/lrama/pull/337
|
46
|
+
|
3
47
|
## Lrama 0.6.0 (2023-12-25)
|
4
48
|
|
5
49
|
### User defined parameterizing rules
|
@@ -20,6 +64,8 @@ stmt: pair(ODD, EVEN) <num>
|
|
20
64
|
;
|
21
65
|
```
|
22
66
|
|
67
|
+
https://github.com/ruby/lrama/pull/285
|
68
|
+
|
23
69
|
## Lrama 0.5.11 (2023-12-02)
|
24
70
|
|
25
71
|
### Type specification of parameterizing rules
|
data/Steepfile
CHANGED
@@ -4,13 +4,12 @@ target :lib do
|
|
4
4
|
repo_path '.gem_rbs_collection/'
|
5
5
|
signature "sig"
|
6
6
|
|
7
|
+
check "lib/lrama/grammar/binding.rb"
|
7
8
|
check "lib/lrama/grammar/code/printer_code.rb"
|
8
9
|
check "lib/lrama/grammar/code.rb"
|
9
10
|
check "lib/lrama/grammar/counter.rb"
|
10
11
|
check "lib/lrama/grammar/error_token.rb"
|
11
|
-
check "lib/lrama/grammar/
|
12
|
-
check "lib/lrama/grammar/parameterizing_rule_resolver.rb"
|
13
|
-
check "lib/lrama/grammar/parameterizing_rule_rhs_builder.rb"
|
12
|
+
check "lib/lrama/grammar/parameterizing_rule"
|
14
13
|
check "lib/lrama/grammar/parameterizing_rules"
|
15
14
|
check "lib/lrama/grammar/percent_code.rb"
|
16
15
|
check "lib/lrama/grammar/precedence.rb"
|
data/lib/lrama/command.rb
CHANGED
@@ -1,14 +1,28 @@
|
|
1
1
|
module Lrama
|
2
2
|
class Command
|
3
3
|
def run(argv)
|
4
|
-
|
4
|
+
begin
|
5
|
+
options = OptionParser.new.parse(argv)
|
6
|
+
rescue => e
|
7
|
+
message = e.message
|
8
|
+
message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
|
9
|
+
abort message
|
10
|
+
end
|
5
11
|
|
6
12
|
Report::Duration.enable if options.trace_opts[:time]
|
7
13
|
|
8
14
|
warning = Lrama::Warning.new
|
9
15
|
text = options.y.read
|
10
16
|
options.y.close if options.y != STDIN
|
11
|
-
|
17
|
+
parser = Lrama::Parser.new(text, options.grammar_file, options.debug)
|
18
|
+
begin
|
19
|
+
grammar = parser.parse
|
20
|
+
rescue => e
|
21
|
+
raise e if options.debug
|
22
|
+
message = e.message
|
23
|
+
message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
|
24
|
+
abort message
|
25
|
+
end
|
12
26
|
states = Lrama::States.new(grammar, warning, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
|
13
27
|
states.compute
|
14
28
|
context = Lrama::Context.new(states)
|
@@ -39,7 +53,7 @@ module Lrama
|
|
39
53
|
end
|
40
54
|
|
41
55
|
if warning.has_error?
|
42
|
-
exit
|
56
|
+
exit false
|
43
57
|
end
|
44
58
|
end
|
45
59
|
end
|
data/lib/lrama/context.rb
CHANGED
@@ -9,7 +9,7 @@ module Lrama
|
|
9
9
|
BaseMin = -Float::INFINITY
|
10
10
|
|
11
11
|
# TODO: It might be better to pass `states` to Output directly?
|
12
|
-
attr_reader :states
|
12
|
+
attr_reader :states, :yylast, :yypact_ninf, :yytable_ninf, :yydefact, :yydefgoto
|
13
13
|
|
14
14
|
def initialize(states)
|
15
15
|
@states = states
|
@@ -41,15 +41,11 @@ module Lrama
|
|
41
41
|
def yyfinal
|
42
42
|
@states.states.find do |state|
|
43
43
|
state.items.find do |item|
|
44
|
-
item.rule.lhs.
|
44
|
+
item.rule.lhs.accept_symbol? && item.end_of_rule?
|
45
45
|
end
|
46
46
|
end.id
|
47
47
|
end
|
48
48
|
|
49
|
-
def yylast
|
50
|
-
@yylast
|
51
|
-
end
|
52
|
-
|
53
49
|
# Number of terms
|
54
50
|
def yyntokens
|
55
51
|
@states.terms.count
|
@@ -119,30 +115,14 @@ module Lrama
|
|
119
115
|
end
|
120
116
|
end
|
121
117
|
|
122
|
-
def yypact_ninf
|
123
|
-
@yypact_ninf
|
124
|
-
end
|
125
|
-
|
126
|
-
def yytable_ninf
|
127
|
-
@yytable_ninf
|
128
|
-
end
|
129
|
-
|
130
118
|
def yypact
|
131
119
|
@base[0...yynstates]
|
132
120
|
end
|
133
121
|
|
134
|
-
def yydefact
|
135
|
-
@yydefact
|
136
|
-
end
|
137
|
-
|
138
122
|
def yypgoto
|
139
123
|
@base[yynstates..-1]
|
140
124
|
end
|
141
125
|
|
142
|
-
def yydefgoto
|
143
|
-
@yydefgoto
|
144
|
-
end
|
145
|
-
|
146
126
|
def yytable
|
147
127
|
@table
|
148
128
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Lrama
|
2
|
+
class Grammar
|
3
|
+
class Binding
|
4
|
+
attr_reader :actual_args, :count
|
5
|
+
|
6
|
+
def initialize(parameterizing_rule, actual_args)
|
7
|
+
@parameters = parameterizing_rule.parameters
|
8
|
+
@actual_args = actual_args
|
9
|
+
@parameter_to_arg = @parameters.zip(actual_args).map do |param, arg|
|
10
|
+
[param.s_value, arg]
|
11
|
+
end.to_h
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve_symbol(symbol)
|
15
|
+
if symbol.is_a?(Lexer::Token::InstantiateRule)
|
16
|
+
resolved_args = symbol.args.map { |arg| resolve_symbol(arg) }
|
17
|
+
Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag)
|
18
|
+
else
|
19
|
+
@parameter_to_arg[symbol.s_value] || symbol
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -22,7 +22,7 @@ module Lrama
|
|
22
22
|
# For the semantic action of original rule:
|
23
23
|
#
|
24
24
|
# "Rule" class: keyword_class { $1 } tSTRING { $2 + $3 } keyword_end { $class = $1 + $keyword_end }
|
25
|
-
# "Position in grammar" $1 $2 $3 $4 $5
|
25
|
+
# "Position in grammar" $1 $2 $3 $4 $5
|
26
26
|
# "Index for yyvsp" -4 -3 -2 -1 0
|
27
27
|
#
|
28
28
|
#
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Lrama
|
2
|
+
class Grammar
|
3
|
+
class ParameterizingRule
|
4
|
+
class Resolver
|
5
|
+
attr_accessor :created_lhs_list
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@rules = []
|
9
|
+
@created_lhs_list = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_parameterizing_rule(rule)
|
13
|
+
@rules << rule
|
14
|
+
end
|
15
|
+
|
16
|
+
def defined?(token)
|
17
|
+
!select_rules(token).empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(token)
|
21
|
+
select_rules(token).last
|
22
|
+
end
|
23
|
+
|
24
|
+
def created_lhs(lhs_s_value)
|
25
|
+
@created_lhs_list.select { |created_lhs| created_lhs.s_value == lhs_s_value }.last
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def select_rules(token)
|
31
|
+
@rules.select do |rule|
|
32
|
+
rule.name == token.rule_name &&
|
33
|
+
rule.required_parameters_count == token.args_count
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Lrama
|
2
|
+
class Grammar
|
3
|
+
class ParameterizingRule
|
4
|
+
class Rule
|
5
|
+
attr_reader :name, :parameters, :rhs_list, :required_parameters_count
|
6
|
+
|
7
|
+
def initialize(name, parameters, rhs_list)
|
8
|
+
@name = name
|
9
|
+
@parameters = parameters
|
10
|
+
@rhs_list = rhs_list
|
11
|
+
@required_parameters_count = parameters.count
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -3,21 +3,22 @@ require 'lrama/grammar/parameterizing_rules/builder'
|
|
3
3
|
module Lrama
|
4
4
|
class Grammar
|
5
5
|
class RuleBuilder
|
6
|
-
attr_accessor :lhs, :
|
7
|
-
attr_reader :rhs, :user_code, :precedence_sym
|
6
|
+
attr_accessor :lhs, :line
|
7
|
+
attr_reader :lhs_tag, :rhs, :user_code, :precedence_sym
|
8
8
|
|
9
|
-
def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, skip_preprocess_references: false)
|
9
|
+
def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false)
|
10
10
|
@rule_counter = rule_counter
|
11
11
|
@midrule_action_counter = midrule_action_counter
|
12
12
|
@position_in_original_rule_rhs = position_in_original_rule_rhs
|
13
13
|
@skip_preprocess_references = skip_preprocess_references
|
14
14
|
|
15
15
|
@lhs = nil
|
16
|
+
@lhs_tag = lhs_tag
|
16
17
|
@rhs = []
|
17
|
-
@lhs_tag = nil
|
18
18
|
@user_code = nil
|
19
19
|
@precedence_sym = nil
|
20
20
|
@line = nil
|
21
|
+
@rule_builders_for_parameterizing_rules = []
|
21
22
|
@rule_builders_for_derived_rules = []
|
22
23
|
end
|
23
24
|
|
@@ -33,7 +34,7 @@ module Lrama
|
|
33
34
|
|
34
35
|
def user_code=(user_code)
|
35
36
|
if !@line
|
36
|
-
@line = user_code
|
37
|
+
@line = user_code&.line
|
37
38
|
end
|
38
39
|
|
39
40
|
flush_user_code
|
@@ -51,14 +52,14 @@ module Lrama
|
|
51
52
|
freeze_rhs
|
52
53
|
end
|
53
54
|
|
54
|
-
def setup_rules(
|
55
|
+
def setup_rules(parameterizing_rule_resolver)
|
55
56
|
preprocess_references unless @skip_preprocess_references
|
56
|
-
process_rhs(
|
57
|
+
process_rhs(parameterizing_rule_resolver)
|
57
58
|
build_rules
|
58
59
|
end
|
59
60
|
|
60
61
|
def rules
|
61
|
-
@parameterizing_rules + @midrule_action_rules + @rules
|
62
|
+
@parameterizing_rules + @old_parameterizing_rules + @midrule_action_rules + @rules
|
62
63
|
end
|
63
64
|
|
64
65
|
private
|
@@ -75,10 +76,13 @@ module Lrama
|
|
75
76
|
tokens = @replaced_rhs
|
76
77
|
|
77
78
|
rule = Rule.new(
|
78
|
-
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, token_code: user_code,
|
79
|
+
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
|
79
80
|
position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
|
80
81
|
)
|
81
82
|
@rules = [rule]
|
83
|
+
@parameterizing_rules = @rule_builders_for_parameterizing_rules.map do |rule_builder|
|
84
|
+
rule_builder.rules
|
85
|
+
end.flatten
|
82
86
|
@midrule_action_rules = @rule_builders_for_derived_rules.map do |rule_builder|
|
83
87
|
rule_builder.rules
|
84
88
|
end.flatten
|
@@ -89,11 +93,11 @@ module Lrama
|
|
89
93
|
|
90
94
|
# rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on.
|
91
95
|
# `#process_rhs` replaces some kind of tokens to `Ident` so that all `@replaced_rhs` are `Ident` or `Char`.
|
92
|
-
def process_rhs(
|
96
|
+
def process_rhs(parameterizing_rule_resolver)
|
93
97
|
return if @replaced_rhs
|
94
98
|
|
95
99
|
@replaced_rhs = []
|
96
|
-
@
|
100
|
+
@old_parameterizing_rules = []
|
97
101
|
|
98
102
|
rhs.each_with_index do |token, i|
|
99
103
|
case token
|
@@ -102,26 +106,46 @@ module Lrama
|
|
102
106
|
when Lrama::Lexer::Token::Ident
|
103
107
|
@replaced_rhs << token
|
104
108
|
when Lrama::Lexer::Token::InstantiateRule
|
105
|
-
if
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
if parameterizing_rule_resolver.defined?(token)
|
110
|
+
parameterizing_rule = parameterizing_rule_resolver.find(token)
|
111
|
+
raise "Unexpected token. #{token}" unless parameterizing_rule
|
112
|
+
|
113
|
+
bindings = Binding.new(parameterizing_rule, token.args)
|
114
|
+
lhs_s_value = lhs_s_value(token, bindings)
|
115
|
+
if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value))
|
116
|
+
@replaced_rhs << created_lhs
|
117
|
+
else
|
118
|
+
lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location)
|
119
|
+
@replaced_rhs << lhs_token
|
120
|
+
parameterizing_rule_resolver.created_lhs_list << lhs_token
|
121
|
+
parameterizing_rule.rhs_list.each do |r|
|
122
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
|
123
|
+
rule_builder.lhs = lhs_token
|
124
|
+
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
|
125
|
+
rule_builder.line = line
|
126
|
+
rule_builder.user_code = r.user_code
|
127
|
+
rule_builder.precedence_sym = r.precedence_sym
|
128
|
+
rule_builder.complete_input
|
129
|
+
rule_builder.setup_rules(parameterizing_rule_resolver)
|
130
|
+
@rule_builders_for_parameterizing_rules << rule_builder
|
131
|
+
end
|
132
|
+
end
|
109
133
|
else
|
110
134
|
# TODO: Delete when the standard library will defined as a grammar file.
|
111
|
-
|
112
|
-
@
|
113
|
-
@replaced_rhs <<
|
135
|
+
parameterizing_rule = ParameterizingRules::Builder.new(token, @rule_counter, token.lhs_tag, user_code, precedence_sym, line)
|
136
|
+
@old_parameterizing_rules = @old_parameterizing_rules + parameterizing_rule.build
|
137
|
+
@replaced_rhs << parameterizing_rule.build_token
|
114
138
|
end
|
115
139
|
when Lrama::Lexer::Token::UserCode
|
116
140
|
prefix = token.referred ? "@" : "$@"
|
117
141
|
new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s)
|
118
142
|
@replaced_rhs << new_token
|
119
143
|
|
120
|
-
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, skip_preprocess_references: true)
|
144
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: lhs_tag, skip_preprocess_references: true)
|
121
145
|
rule_builder.lhs = new_token
|
122
146
|
rule_builder.user_code = token
|
123
147
|
rule_builder.complete_input
|
124
|
-
rule_builder.setup_rules(
|
148
|
+
rule_builder.setup_rules(parameterizing_rule_resolver)
|
125
149
|
|
126
150
|
@rule_builders_for_derived_rules << rule_builder
|
127
151
|
else
|
@@ -130,6 +154,18 @@ module Lrama
|
|
130
154
|
end
|
131
155
|
end
|
132
156
|
|
157
|
+
def lhs_s_value(token, bindings)
|
158
|
+
s_values = token.args.map do |arg|
|
159
|
+
resolved = bindings.resolve_symbol(arg)
|
160
|
+
if resolved.is_a?(Lexer::Token::InstantiateRule)
|
161
|
+
[resolved.s_value, resolved.args.map(&:s_value)]
|
162
|
+
else
|
163
|
+
resolved.s_value
|
164
|
+
end
|
165
|
+
end
|
166
|
+
"#{token.rule_name}_#{s_values.join('_')}"
|
167
|
+
end
|
168
|
+
|
133
169
|
def numberize_references
|
134
170
|
# Bison n'th component is 1-origin
|
135
171
|
(rhs + [user_code]).compact.each.with_index(1) do |token, i|
|
@@ -144,13 +180,11 @@ module Lrama
|
|
144
180
|
candidates = rhs.each_with_index.select {|token, i| token.referred_by?(ref_name) }
|
145
181
|
|
146
182
|
if candidates.size >= 2
|
147
|
-
|
148
|
-
raise location.generate_error_message("Referring symbol `#{ref_name}` is duplicated.")
|
183
|
+
token.invalid_ref(ref, "Referring symbol `#{ref_name}` is duplicated.")
|
149
184
|
end
|
150
185
|
|
151
186
|
unless (referring_symbol = candidates.first)
|
152
|
-
|
153
|
-
raise location.generate_error_message("Referring symbol `#{ref_name}` is not found.")
|
187
|
+
token.invalid_ref(ref, "Referring symbol `#{ref_name}` is not found.")
|
154
188
|
end
|
155
189
|
|
156
190
|
ref.index = referring_symbol[1] + 1
|
@@ -163,7 +197,7 @@ module Lrama
|
|
163
197
|
if ref.index
|
164
198
|
# TODO: Prohibit $0 even so Bison allows it?
|
165
199
|
# See: https://www.gnu.org/software/bison/manual/html_node/Actions.html
|
166
|
-
|
200
|
+
token.invalid_ref(ref, "Can not refer following component. #{ref.index} >= #{i}.") if ref.index >= i
|
167
201
|
rhs[ref.index - 1].referred = true
|
168
202
|
end
|
169
203
|
end
|
data/lib/lrama/grammar/type.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
module Lrama
|
2
2
|
class Grammar
|
3
|
-
class Type
|
3
|
+
class Type
|
4
|
+
attr_reader :id, :tag
|
5
|
+
|
6
|
+
def initialize(id:, tag:)
|
7
|
+
@id = id
|
8
|
+
@tag = tag
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
self.class == other.class &&
|
13
|
+
self.id == other.id &&
|
14
|
+
self.tag == other.tag
|
15
|
+
end
|
4
16
|
end
|
5
17
|
end
|
6
18
|
end
|
data/lib/lrama/grammar.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "lrama/grammar/auxiliary"
|
2
|
+
require "lrama/grammar/binding"
|
2
3
|
require "lrama/grammar/code"
|
3
4
|
require "lrama/grammar/counter"
|
4
5
|
require "lrama/grammar/error_token"
|
@@ -8,9 +9,6 @@ require "lrama/grammar/printer"
|
|
8
9
|
require "lrama/grammar/reference"
|
9
10
|
require "lrama/grammar/rule"
|
10
11
|
require "lrama/grammar/rule_builder"
|
11
|
-
require "lrama/grammar/parameterizing_rule_builder"
|
12
|
-
require "lrama/grammar/parameterizing_rule_resolver"
|
13
|
-
require "lrama/grammar/parameterizing_rule_rhs_builder"
|
14
12
|
require "lrama/grammar/parameterizing_rule"
|
15
13
|
require "lrama/grammar/symbol"
|
16
14
|
require "lrama/grammar/type"
|
@@ -40,7 +38,7 @@ module Lrama
|
|
40
38
|
@rule_builders = []
|
41
39
|
@rules = []
|
42
40
|
@sym_to_rules = {}
|
43
|
-
@
|
41
|
+
@parameterizing_rule_resolver = ParameterizingRule::Resolver.new
|
44
42
|
@empty_symbol = nil
|
45
43
|
@eof_symbol = nil
|
46
44
|
@error_symbol = nil
|
@@ -52,7 +50,7 @@ module Lrama
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def add_percent_code(id:, code:)
|
55
|
-
@percent_codes << PercentCode.new(id, code)
|
53
|
+
@percent_codes << PercentCode.new(id.s_value, code.s_value)
|
56
54
|
end
|
57
55
|
|
58
56
|
def add_printer(ident_or_tags:, token_code:, lineno:)
|
@@ -134,8 +132,8 @@ module Lrama
|
|
134
132
|
@rule_builders << builder
|
135
133
|
end
|
136
134
|
|
137
|
-
def
|
138
|
-
@
|
135
|
+
def add_parameterizing_rule(rule)
|
136
|
+
@parameterizing_rule_resolver.add_parameterizing_rule(rule)
|
139
137
|
end
|
140
138
|
|
141
139
|
def prologue_first_lineno=(prologue_first_lineno)
|
@@ -171,7 +169,7 @@ module Lrama
|
|
171
169
|
|
172
170
|
# TODO: More validation methods
|
173
171
|
#
|
174
|
-
# *
|
172
|
+
# * Validation for no_declared_type_reference
|
175
173
|
def validate!
|
176
174
|
validate_symbol_number_uniqueness!
|
177
175
|
validate_symbol_alias_name_uniqueness!
|
@@ -319,7 +317,7 @@ module Lrama
|
|
319
317
|
|
320
318
|
def setup_rules
|
321
319
|
@rule_builders.each do |builder|
|
322
|
-
builder.setup_rules(@
|
320
|
+
builder.setup_rules(@parameterizing_rule_resolver)
|
323
321
|
end
|
324
322
|
end
|
325
323
|
|