lrama 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|