lrama 0.6.1 → 0.6.2
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 +7 -2
- data/NEWS.md +9 -0
- data/lib/lrama/command.rb +10 -2
- data/lib/lrama/context.rb +2 -2
- data/lib/lrama/counterexamples/example.rb +2 -2
- data/lib/lrama/grammar/code.rb +1 -1
- data/lib/lrama/grammar/parameterizing_rule/resolver.rb +17 -9
- data/lib/lrama/grammar/rule.rb +2 -2
- data/lib/lrama/grammar/rule_builder.rb +31 -36
- data/lib/lrama/grammar/stdlib.y +80 -0
- data/lib/lrama/grammar.rb +11 -2
- data/lib/lrama/lexer.rb +1 -0
- data/lib/lrama/parser.rb +474 -451
- data/lib/lrama/states/item.rb +17 -13
- data/lib/lrama/states_reporter.rb +8 -10
- data/lib/lrama/version.rb +1 -1
- data/parser.y +4 -5
- data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +1 -0
- metadata +3 -16
- data/lib/lrama/grammar/parameterizing_rules/builder/base.rb +0 -36
- data/lib/lrama/grammar/parameterizing_rules/builder/list.rb +0 -28
- data/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb +0 -28
- data/lib/lrama/grammar/parameterizing_rules/builder/option.rb +0 -28
- data/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb +0 -39
- data/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb +0 -34
- data/lib/lrama/grammar/parameterizing_rules/builder.rb +0 -60
- data/sig/lrama/grammar/parameterizing_rules/builder/base.rbs +0 -28
- data/sig/lrama/grammar/parameterizing_rules/builder/list.rbs +0 -10
- data/sig/lrama/grammar/parameterizing_rules/builder/nonempty_list.rbs +0 -10
- data/sig/lrama/grammar/parameterizing_rules/builder/option.rbs +0 -10
- data/sig/lrama/grammar/parameterizing_rules/builder/separated_list.rbs +0 -13
- data/sig/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rbs +0 -13
- data/sig/lrama/grammar/parameterizing_rules/builder.rbs +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4158de45c42ff62eacfb00737261feaa49d8f0cc646004e30da74ba4e2e69c6
|
4
|
+
data.tar.gz: 734830227f701e18df2e9e8bc3da55d15f49c890e08530e6ac55ef87ae5f952d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52ebbe4d099ae63d73aa995bddc8e966f989a4d00ad3b39634d2abe2448da404dd9bff8f15e0dedd0577716089329c804ef2c4edcadd39ca6ba47f8d293d101d
|
7
|
+
data.tar.gz: 72e91c79618071b5850c85335cfe3f1b63ff89f11cd332b0141623a4e2a7e2c2c389dd0db9afe38a5a84b7aa891ac1834fc7a2d6c6eed8f62d87734f6b99cbbf
|
data/.github/workflows/test.yaml
CHANGED
@@ -87,6 +87,11 @@ jobs:
|
|
87
87
|
bundler-cache: true
|
88
88
|
- run: bundle install
|
89
89
|
|
90
|
+
# Copy from https://github.com/ruby/ruby/blob/cb9a47f2acd6e373ef868b890a9d07da6f565dd4/.github/workflows/check_misc.yml#L31
|
91
|
+
- name: Check if C-sources are US-ASCII
|
92
|
+
run: |
|
93
|
+
grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || :
|
94
|
+
|
90
95
|
# Copy from https://github.com/ruby/ruby/blob/089227e94823542acfdafa68541d330eee42ffea/.github/workflows/check_misc.yml#L27
|
91
96
|
- name: Check for trailing spaces
|
92
97
|
run: |
|
@@ -120,8 +125,8 @@ jobs:
|
|
120
125
|
fail-fast: false
|
121
126
|
matrix:
|
122
127
|
# '3.0' is the oldest living ruby version
|
123
|
-
# '2.
|
124
|
-
baseruby: ['head', '3.0', '2.
|
128
|
+
# '2.7' is for BASERUBY
|
129
|
+
baseruby: ['head', '3.0', '2.7']
|
125
130
|
ruby_branch: ['master']
|
126
131
|
defaults:
|
127
132
|
run:
|
data/NEWS.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# NEWS for Lrama
|
2
2
|
|
3
|
+
## Lrama 0.6.2 (2024-01-27)
|
4
|
+
|
5
|
+
### %no-stdlib directive
|
6
|
+
|
7
|
+
If `%no-stdlib` directive is set, Lrama doesn't load Lrama standard library for
|
8
|
+
parameterizing rules, stdlib.y.
|
9
|
+
|
10
|
+
https://github.com/ruby/lrama/pull/344
|
11
|
+
|
3
12
|
## Lrama 0.6.1 (2024-01-13)
|
4
13
|
|
5
14
|
### Nested parameterizing rules
|
data/lib/lrama/command.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Lrama
|
2
2
|
class Command
|
3
|
+
LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__)))
|
4
|
+
STDLIB_FILE_PATH = File.join(LRAMA_LIB, 'grammar', 'stdlib.y')
|
5
|
+
|
3
6
|
def run(argv)
|
4
7
|
begin
|
5
8
|
options = OptionParser.new.parse(argv)
|
@@ -14,9 +17,14 @@ module Lrama
|
|
14
17
|
warning = Lrama::Warning.new
|
15
18
|
text = options.y.read
|
16
19
|
options.y.close if options.y != STDIN
|
17
|
-
parser = Lrama::Parser.new(text, options.grammar_file, options.debug)
|
18
20
|
begin
|
19
|
-
grammar =
|
21
|
+
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse
|
22
|
+
unless grammar.no_stdlib
|
23
|
+
stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
|
24
|
+
grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
|
25
|
+
end
|
26
|
+
grammar.prepare
|
27
|
+
grammar.validate!
|
20
28
|
rescue => e
|
21
29
|
raise e if options.debug
|
22
30
|
message = e.message
|
data/lib/lrama/context.rb
CHANGED
@@ -41,7 +41,7 @@ module Lrama
|
|
41
41
|
def yyfinal
|
42
42
|
@states.states.find do |state|
|
43
43
|
state.items.find do |item|
|
44
|
-
item.
|
44
|
+
item.lhs.accept_symbol? && item.end_of_rule?
|
45
45
|
end
|
46
46
|
end.id
|
47
47
|
end
|
@@ -221,7 +221,7 @@ module Lrama
|
|
221
221
|
|
222
222
|
if state.reduces.map(&:selected_look_ahead).any? {|la| !la.empty? }
|
223
223
|
# Iterate reduces with reverse order so that first rule is used.
|
224
|
-
state.reduces.
|
224
|
+
state.reduces.reverse_each do |reduce|
|
225
225
|
reduce.look_ahead.each do |term|
|
226
226
|
actions[term.number] = rule_id_to_action_number(reduce.rule.id)
|
227
227
|
end
|
@@ -40,7 +40,7 @@ module Lrama
|
|
40
40
|
current = :production
|
41
41
|
lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil
|
42
42
|
|
43
|
-
paths.
|
43
|
+
paths.reverse_each do |path|
|
44
44
|
item = path.to.item
|
45
45
|
|
46
46
|
case current
|
@@ -97,7 +97,7 @@ module Lrama
|
|
97
97
|
if next_sym == sym
|
98
98
|
derivation = nil
|
99
99
|
|
100
|
-
sis.
|
100
|
+
sis.reverse_each do |si|
|
101
101
|
derivation = Derivation.new(si.item, derivation)
|
102
102
|
end
|
103
103
|
|
data/lib/lrama/grammar/code.rb
CHANGED
@@ -2,7 +2,7 @@ module Lrama
|
|
2
2
|
class Grammar
|
3
3
|
class ParameterizingRule
|
4
4
|
class Resolver
|
5
|
-
attr_accessor :created_lhs_list
|
5
|
+
attr_accessor :rules, :created_lhs_list
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@rules = []
|
@@ -13,24 +13,32 @@ module Lrama
|
|
13
13
|
@rules << rule
|
14
14
|
end
|
15
15
|
|
16
|
-
def defined?(token)
|
17
|
-
!select_rules(token).empty?
|
18
|
-
end
|
19
|
-
|
20
16
|
def find(token)
|
21
17
|
select_rules(token).last
|
22
18
|
end
|
23
19
|
|
24
20
|
def created_lhs(lhs_s_value)
|
25
|
-
@created_lhs_list.
|
21
|
+
@created_lhs_list.reverse.find { |created_lhs| created_lhs.s_value == lhs_s_value }
|
26
22
|
end
|
27
23
|
|
28
24
|
private
|
29
25
|
|
30
26
|
def select_rules(token)
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
rules = select_rules_by_name(token.rule_name)
|
28
|
+
rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
|
29
|
+
if rules.empty?
|
30
|
+
raise "Invalid number of arguments. `#{token.rule_name}`"
|
31
|
+
else
|
32
|
+
rules
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def select_rules_by_name(rule_name)
|
37
|
+
rules = @rules.select { |rule| rule.name == rule_name }
|
38
|
+
if rules.empty?
|
39
|
+
raise "Parameterizing rule does not exist. `#{rule_name}`"
|
40
|
+
else
|
41
|
+
rules
|
34
42
|
end
|
35
43
|
end
|
36
44
|
end
|
data/lib/lrama/grammar/rule.rb
CHANGED
@@ -19,7 +19,7 @@ module Lrama
|
|
19
19
|
# TODO: Change this to display_name
|
20
20
|
def to_s
|
21
21
|
l = lhs.id.s_value
|
22
|
-
r =
|
22
|
+
r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(", ")
|
23
23
|
|
24
24
|
"#{l} -> #{r}"
|
25
25
|
end
|
@@ -27,7 +27,7 @@ module Lrama
|
|
27
27
|
# Used by #user_actions
|
28
28
|
def as_comment
|
29
29
|
l = lhs.id.s_value
|
30
|
-
r =
|
30
|
+
r = empty_rule? ? "%empty" : rhs.map(&:display_name).join(" ")
|
31
31
|
|
32
32
|
"#{l}: #{r}"
|
33
33
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'lrama/grammar/parameterizing_rules/builder'
|
2
|
-
|
3
1
|
module Lrama
|
4
2
|
class Grammar
|
5
3
|
class RuleBuilder
|
@@ -59,7 +57,7 @@ module Lrama
|
|
59
57
|
end
|
60
58
|
|
61
59
|
def rules
|
62
|
-
@parameterizing_rules + @
|
60
|
+
@parameterizing_rules + @midrule_action_rules + @rules
|
63
61
|
end
|
64
62
|
|
65
63
|
private
|
@@ -97,7 +95,6 @@ module Lrama
|
|
97
95
|
return if @replaced_rhs
|
98
96
|
|
99
97
|
@replaced_rhs = []
|
100
|
-
@old_parameterizing_rules = []
|
101
98
|
|
102
99
|
rhs.each_with_index do |token, i|
|
103
100
|
case token
|
@@ -106,35 +103,28 @@ module Lrama
|
|
106
103
|
when Lrama::Lexer::Token::Ident
|
107
104
|
@replaced_rhs << token
|
108
105
|
when Lrama::Lexer::Token::InstantiateRule
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
106
|
+
parameterizing_rule = parameterizing_rule_resolver.find(token)
|
107
|
+
raise "Unexpected token. #{token}" unless parameterizing_rule
|
108
|
+
|
109
|
+
bindings = Binding.new(parameterizing_rule, token.args)
|
110
|
+
lhs_s_value = lhs_s_value(token, bindings)
|
111
|
+
if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value))
|
112
|
+
@replaced_rhs << created_lhs
|
133
113
|
else
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
114
|
+
lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location)
|
115
|
+
@replaced_rhs << lhs_token
|
116
|
+
parameterizing_rule_resolver.created_lhs_list << lhs_token
|
117
|
+
parameterizing_rule.rhs_list.each do |r|
|
118
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
|
119
|
+
rule_builder.lhs = lhs_token
|
120
|
+
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
|
121
|
+
rule_builder.line = line
|
122
|
+
rule_builder.user_code = r.user_code
|
123
|
+
rule_builder.precedence_sym = r.precedence_sym
|
124
|
+
rule_builder.complete_input
|
125
|
+
rule_builder.setup_rules(parameterizing_rule_resolver)
|
126
|
+
@rule_builders_for_parameterizing_rules << rule_builder
|
127
|
+
end
|
138
128
|
end
|
139
129
|
when Lrama::Lexer::Token::UserCode
|
140
130
|
prefix = token.referred ? "@" : "$@"
|
@@ -173,11 +163,12 @@ module Lrama
|
|
173
163
|
|
174
164
|
token.references.each do |ref|
|
175
165
|
ref_name = ref.name
|
176
|
-
|
177
|
-
|
166
|
+
|
167
|
+
if ref_name
|
168
|
+
if ref_name == '$'
|
178
169
|
ref.name = '$'
|
179
170
|
else
|
180
|
-
candidates = rhs.each_with_index.select {|token,
|
171
|
+
candidates = ([lhs] + rhs).each_with_index.select {|token, _i| token.referred_by?(ref_name) }
|
181
172
|
|
182
173
|
if candidates.size >= 2
|
183
174
|
token.invalid_ref(ref, "Referring symbol `#{ref_name}` is duplicated.")
|
@@ -187,7 +178,11 @@ module Lrama
|
|
187
178
|
token.invalid_ref(ref, "Referring symbol `#{ref_name}` is not found.")
|
188
179
|
end
|
189
180
|
|
190
|
-
|
181
|
+
if referring_symbol[1] == 0 # Refers to LHS
|
182
|
+
ref.name = '$'
|
183
|
+
else
|
184
|
+
ref.index = referring_symbol[1]
|
185
|
+
end
|
191
186
|
end
|
192
187
|
end
|
193
188
|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
/**********************************************************************
|
2
|
+
|
3
|
+
stdlib.y
|
4
|
+
|
5
|
+
This is lrama's standard library. It provides a number of
|
6
|
+
parameterizing rule definitions, such as options and lists,
|
7
|
+
that should be useful in a number of situations.
|
8
|
+
|
9
|
+
**********************************************************************/
|
10
|
+
|
11
|
+
/*
|
12
|
+
* program: option(number)
|
13
|
+
*
|
14
|
+
* =>
|
15
|
+
*
|
16
|
+
* program: option_number
|
17
|
+
* option_number: %empty
|
18
|
+
* option_number: number
|
19
|
+
*/
|
20
|
+
%rule option(X): /* empty */
|
21
|
+
| X
|
22
|
+
;
|
23
|
+
|
24
|
+
/*
|
25
|
+
* program: list(number)
|
26
|
+
*
|
27
|
+
* =>
|
28
|
+
*
|
29
|
+
* program: list_number
|
30
|
+
* list_number: %empty
|
31
|
+
* list_number: list_number number
|
32
|
+
*/
|
33
|
+
%rule list(X): /* empty */
|
34
|
+
| list(X) X
|
35
|
+
;
|
36
|
+
|
37
|
+
/*
|
38
|
+
* program: nonempty_list(number)
|
39
|
+
*
|
40
|
+
* =>
|
41
|
+
*
|
42
|
+
* program: nonempty_list_number
|
43
|
+
* nonempty_list_number: number
|
44
|
+
* nonempty_list_number: nonempty_list_number number
|
45
|
+
*/
|
46
|
+
%rule nonempty_list(X): X
|
47
|
+
| nonempty_list(X) X
|
48
|
+
;
|
49
|
+
|
50
|
+
/*
|
51
|
+
* program: separated_nonempty_list(comma, number)
|
52
|
+
*
|
53
|
+
* =>
|
54
|
+
*
|
55
|
+
* program: separated_nonempty_list_comma_number
|
56
|
+
* separated_nonempty_list_comma_number: number
|
57
|
+
* separated_nonempty_list_comma_number: separated_nonempty_list_comma_number comma number
|
58
|
+
*/
|
59
|
+
%rule separated_nonempty_list(separator, X): X
|
60
|
+
| separated_nonempty_list(separator, X) separator X
|
61
|
+
;
|
62
|
+
|
63
|
+
/*
|
64
|
+
* program: separated_list(comma, number)
|
65
|
+
*
|
66
|
+
* =>
|
67
|
+
*
|
68
|
+
* program: separated_list_comma_number
|
69
|
+
* separated_list_comma_number: option_separated_nonempty_list_comma_number
|
70
|
+
* option_separated_nonempty_list_comma_number: %empty
|
71
|
+
* option_separated_nonempty_list_comma_number: separated_nonempty_list_comma_number
|
72
|
+
* separated_nonempty_list_comma_number: number
|
73
|
+
* separated_nonempty_list_comma_number: comma separated_nonempty_list_comma_number number
|
74
|
+
*/
|
75
|
+
%rule separated_list(separator, X): option(separated_nonempty_list(separator, X))
|
76
|
+
;
|
77
|
+
|
78
|
+
%%
|
79
|
+
|
80
|
+
%union{};
|
data/lib/lrama/grammar.rb
CHANGED
@@ -24,7 +24,7 @@ module Lrama
|
|
24
24
|
:lex_param, :parse_param, :initial_action,
|
25
25
|
:symbols, :types,
|
26
26
|
:rules, :rule_builders,
|
27
|
-
:sym_to_rules
|
27
|
+
:sym_to_rules, :no_stdlib
|
28
28
|
|
29
29
|
def initialize(rule_counter)
|
30
30
|
@rule_counter = rule_counter
|
@@ -45,6 +45,7 @@ module Lrama
|
|
45
45
|
@undef_symbol = nil
|
46
46
|
@accept_symbol = nil
|
47
47
|
@aux = Auxiliary.new
|
48
|
+
@no_stdlib = false
|
48
49
|
|
49
50
|
append_special_symbols
|
50
51
|
end
|
@@ -136,6 +137,14 @@ module Lrama
|
|
136
137
|
@parameterizing_rule_resolver.add_parameterizing_rule(rule)
|
137
138
|
end
|
138
139
|
|
140
|
+
def parameterizing_rules
|
141
|
+
@parameterizing_rule_resolver.rules
|
142
|
+
end
|
143
|
+
|
144
|
+
def insert_before_parameterizing_rules(rules)
|
145
|
+
@parameterizing_rule_resolver.rules = rules + @parameterizing_rule_resolver.rules
|
146
|
+
end
|
147
|
+
|
139
148
|
def prologue_first_lineno=(prologue_first_lineno)
|
140
149
|
@aux.prologue_first_lineno = prologue_first_lineno
|
141
150
|
end
|
@@ -234,7 +243,7 @@ module Lrama
|
|
234
243
|
def compute_nullable
|
235
244
|
@rules.each do |rule|
|
236
245
|
case
|
237
|
-
when rule.
|
246
|
+
when rule.empty_rule?
|
238
247
|
rule.nullable = true
|
239
248
|
when rule.rhs.any?(&:term)
|
240
249
|
rule.nullable = false
|