lrama 0.5.12 → 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 +66 -0
- data/README.md +14 -3
- data/Steepfile +2 -0
- 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/printer_code.rb +1 -1
- data/lib/lrama/grammar/code/rule_action.rb +2 -2
- data/lib/lrama/grammar/code.rb +19 -7
- 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 -0
- data/lib/lrama/grammar/percent_code.rb +3 -3
- data/lib/lrama/grammar/rule_builder.rb +69 -31
- data/lib/lrama/grammar/type.rb +13 -1
- data/lib/lrama/grammar.rb +15 -43
- data/lib/lrama/lexer/grammar_file.rb +21 -0
- data/lib/lrama/lexer/location.rb +77 -2
- data/lib/lrama/lexer/token/instantiate_rule.rb +23 -0
- data/lib/lrama/lexer/token/user_code.rb +10 -10
- data/lib/lrama/lexer/token.rb +6 -1
- data/lib/lrama/lexer.rb +23 -18
- data/lib/lrama/output.rb +2 -2
- data/lib/lrama/parser.rb +641 -458
- data/lib/lrama/states_reporter.rb +1 -1
- data/lib/lrama/version.rb +1 -1
- data/parser.y +97 -32
- data/sig/lrama/grammar/binding.rbs +16 -0
- data/sig/lrama/grammar/code/printer_code.rbs +1 -1
- data/sig/lrama/grammar/code.rbs +5 -5
- 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 +6 -0
- data/sig/lrama/grammar/parameterizing_rules/builder/base.rbs +2 -2
- data/sig/lrama/grammar/parameterizing_rules/builder.rbs +1 -1
- data/sig/lrama/grammar/percent_code.rbs +3 -3
- data/sig/lrama/grammar/rule_builder.rbs +9 -8
- data/sig/lrama/lexer/grammar_file.rbs +15 -0
- data/sig/lrama/lexer/location.rbs +13 -1
- data/sig/lrama/lexer/token/instantiate_rule.rbs +14 -0
- data/sig/lrama/lexer/token.rbs +1 -0
- metadata +17 -5
- data/lib/lrama/lexer/token/parameterizing.rb +0 -34
- data/sig/lrama/lexer/token/parameterizing.rbs +0 -17
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.
|
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,71 @@
|
|
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
|
+
|
47
|
+
## Lrama 0.6.0 (2023-12-25)
|
48
|
+
|
49
|
+
### User defined parameterizing rules
|
50
|
+
|
51
|
+
Allow to define parameterizing rule by `%rule` directive.
|
52
|
+
|
53
|
+
```
|
54
|
+
%rule pair(X, Y): X Y { $$ = $1 + $2; }
|
55
|
+
;
|
56
|
+
|
57
|
+
%%
|
58
|
+
|
59
|
+
program: stmt
|
60
|
+
;
|
61
|
+
|
62
|
+
stmt: pair(ODD, EVEN) <num>
|
63
|
+
| pair(EVEN, ODD) <num>
|
64
|
+
;
|
65
|
+
```
|
66
|
+
|
67
|
+
https://github.com/ruby/lrama/pull/285
|
68
|
+
|
3
69
|
## Lrama 0.5.11 (2023-12-02)
|
4
70
|
|
5
71
|
### Type specification of parameterizing rules
|
data/README.md
CHANGED
@@ -49,9 +49,13 @@ Enter the formula:
|
|
49
49
|
|
50
50
|
## Versions and Branches
|
51
51
|
|
52
|
-
###
|
52
|
+
### v0_6 (`master` branch)
|
53
53
|
|
54
|
-
This branch is for Ruby 3.
|
54
|
+
This branch is for Ruby 3.4. `lrama_0_6` branch is created from this branch, once Ruby 3.4 is released.
|
55
|
+
|
56
|
+
### v0_5 (`lrama_0_5` branch)
|
57
|
+
|
58
|
+
This branch is for Ruby 3.3.
|
55
59
|
|
56
60
|
### v0_4 (`lrama_0_4` branch)
|
57
61
|
|
@@ -91,6 +95,13 @@ $ bundle exec rbs collection install
|
|
91
95
|
$ bundle exec steep check
|
92
96
|
```
|
93
97
|
|
98
|
+
Running both of them:
|
99
|
+
|
100
|
+
```shell
|
101
|
+
$ bundle install
|
102
|
+
$ bundle exec rake
|
103
|
+
```
|
104
|
+
|
94
105
|
### Profiling Lrama
|
95
106
|
|
96
107
|
#### 1. Create parse.tmp.y in ruby/ruby
|
@@ -136,7 +147,7 @@ $ stackprof --d3-flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph.html
|
|
136
147
|
|
137
148
|
## Release flow
|
138
149
|
|
139
|
-
1. Update `Lrama::VERSION`
|
150
|
+
1. Update `Lrama::VERSION` and NEWS.md
|
140
151
|
2. Release as a gem by `rake release`
|
141
152
|
3. Update Lrama in ruby/ruby by `cp -r LEGAL.md NEWS.md MIT exe lib template ruby/tool/lrama`
|
142
153
|
4. Create new release on [GitHub](https://github.com/ruby/lrama/releases)
|
data/Steepfile
CHANGED
@@ -4,10 +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"
|
12
|
+
check "lib/lrama/grammar/parameterizing_rule"
|
11
13
|
check "lib/lrama/grammar/parameterizing_rules"
|
12
14
|
check "lib/lrama/grammar/percent_code.rb"
|
13
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
|
@@ -2,7 +2,7 @@ module Lrama
|
|
2
2
|
class Grammar
|
3
3
|
class Code
|
4
4
|
class RuleAction < Code
|
5
|
-
def initialize(type
|
5
|
+
def initialize(type:, token_code:, rule:)
|
6
6
|
super(type: type, token_code: token_code)
|
7
7
|
@rule = rule
|
8
8
|
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
|
#
|
data/lib/lrama/grammar/code.rb
CHANGED
@@ -1,12 +1,29 @@
|
|
1
1
|
require "forwardable"
|
2
|
+
require "lrama/grammar/code/initial_action_code"
|
3
|
+
require "lrama/grammar/code/no_reference_code"
|
4
|
+
require "lrama/grammar/code/printer_code"
|
5
|
+
require "lrama/grammar/code/rule_action"
|
2
6
|
|
3
7
|
module Lrama
|
4
8
|
class Grammar
|
5
|
-
class Code
|
9
|
+
class Code
|
6
10
|
extend Forwardable
|
7
11
|
|
8
12
|
def_delegators "token_code", :s_value, :line, :column, :references
|
9
13
|
|
14
|
+
attr_reader :type, :token_code
|
15
|
+
|
16
|
+
def initialize(type:, token_code:)
|
17
|
+
@type = type
|
18
|
+
@token_code = token_code
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
self.class == other.class &&
|
23
|
+
self.type == other.type &&
|
24
|
+
self.token_code == other.token_code
|
25
|
+
end
|
26
|
+
|
10
27
|
# $$, $n, @$, @n are translated to C code
|
11
28
|
def translated_code
|
12
29
|
t_code = s_value.dup
|
@@ -17,7 +34,7 @@ module Lrama
|
|
17
34
|
|
18
35
|
str = reference_to_c(ref)
|
19
36
|
|
20
|
-
t_code[first_column
|
37
|
+
t_code[first_column...last_column] = str
|
21
38
|
end
|
22
39
|
|
23
40
|
return t_code
|
@@ -31,8 +48,3 @@ module Lrama
|
|
31
48
|
end
|
32
49
|
end
|
33
50
|
end
|
34
|
-
|
35
|
-
require "lrama/grammar/code/initial_action_code"
|
36
|
-
require "lrama/grammar/code/no_reference_code"
|
37
|
-
require "lrama/grammar/code/printer_code"
|
38
|
-
require "lrama/grammar/code/rule_action"
|
@@ -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
|