lrama 0.6.11 → 0.7.0
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/gh-pages.yml +46 -0
- data/.github/workflows/test.yaml +35 -7
- data/.gitignore +1 -0
- data/.rdoc_options +2 -0
- data/Gemfile +4 -2
- data/NEWS.md +60 -0
- data/README.md +44 -15
- data/Rakefile +13 -1
- data/Steepfile +2 -0
- data/doc/Index.md +58 -0
- data/lib/lrama/bitmap.rb +3 -0
- data/lib/lrama/command.rb +2 -1
- data/lib/lrama/digraph.rb +30 -0
- data/lib/lrama/grammar/binding.rb +47 -15
- data/lib/lrama/grammar/rule.rb +8 -0
- data/lib/lrama/grammar/rule_builder.rb +3 -15
- data/lib/lrama/grammar.rb +8 -3
- data/lib/lrama/lexer/grammar_file.rb +8 -1
- data/lib/lrama/lexer/location.rb +17 -1
- data/lib/lrama/lexer/token/char.rb +1 -0
- data/lib/lrama/lexer/token/ident.rb +1 -0
- data/lib/lrama/lexer/token/instantiate_rule.rb +6 -1
- data/lib/lrama/lexer/token/tag.rb +3 -1
- data/lib/lrama/lexer/token/user_code.rb +5 -1
- data/lib/lrama/lexer/token.rb +14 -2
- data/lib/lrama/lexer.rb +4 -5
- data/lib/lrama/logger.rb +4 -0
- data/lib/lrama/option_parser.rb +10 -8
- data/lib/lrama/options.rb +2 -1
- data/lib/lrama/parser.rb +10 -4
- data/lib/lrama/state.rb +288 -1
- data/lib/lrama/states/item.rb +8 -0
- data/lib/lrama/states.rb +69 -2
- data/lib/lrama/trace_reporter.rb +17 -2
- data/lib/lrama/version.rb +1 -1
- data/lrama.gemspec +1 -1
- data/parser.y +4 -3
- data/rbs_collection.lock.yaml +3 -3
- data/sig/generated/lrama/bitmap.rbs +11 -0
- data/sig/generated/lrama/digraph.rbs +39 -0
- data/sig/generated/lrama/grammar/binding.rbs +34 -0
- data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
- data/sig/generated/lrama/lexer/location.rbs +52 -0
- data/sig/{lrama → generated/lrama}/lexer/token/char.rbs +2 -0
- data/sig/{lrama → generated/lrama}/lexer/token/ident.rbs +2 -0
- data/sig/{lrama → generated/lrama}/lexer/token/instantiate_rule.rbs +8 -0
- data/sig/{lrama → generated/lrama}/lexer/token/tag.rbs +3 -0
- data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +6 -1
- data/sig/{lrama → generated/lrama}/lexer/token.rbs +26 -3
- data/sig/generated/lrama/logger.rbs +14 -0
- data/sig/generated/lrama/trace_reporter.rbs +25 -0
- data/sig/lrama/grammar/rule_builder.rbs +0 -1
- data/sig/lrama/options.rbs +1 -0
- metadata +19 -14
- data/sig/lrama/bitmap.rbs +0 -7
- data/sig/lrama/digraph.rbs +0 -23
- data/sig/lrama/grammar/binding.rbs +0 -19
- data/sig/lrama/lexer/grammar_file.rbs +0 -17
- data/sig/lrama/lexer/location.rbs +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9c967547ee9de2d87e1e275bf5d9b1f525b7040f110ee41b9144b163923a3dd6
|
|
4
|
+
data.tar.gz: f9ada41c05e186245e11dfca1dc31da2f2bf8987090b91ed5312369ad1306e64
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: efa3c528e1f8070c26b42e71329c058b874b530d3e13a64047898928099994a94de131a05c491464cdd566c806a2424e427113987f5240ec13e281c7bcb9bdd2
|
|
7
|
+
data.tar.gz: da9ea52d9fa0534e168baf3f62fab8df091caca127201c085c641552fd3f7aaf09ad7f60ad49725a8874b444eb655e881064481907bd1f5ba82481d9db118398
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Deploy Lrama documentation to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["master"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: "pages"
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
if: ${{ github.repository == 'ruby/lrama' && !startsWith(github.event_name, 'pull') }}
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
- name: Setup Ruby
|
|
25
|
+
uses: ruby/setup-ruby@f26937343756480a8cb3ae1f623b9c8d89ed6984 # v1.196.0
|
|
26
|
+
with:
|
|
27
|
+
ruby-version: "3.4"
|
|
28
|
+
bundler-cache: true
|
|
29
|
+
- name: Setup Pages
|
|
30
|
+
id: pages
|
|
31
|
+
uses: actions/configure-pages@v5
|
|
32
|
+
- name: Build with Lrama
|
|
33
|
+
run: bundle exec rake rdoc
|
|
34
|
+
- name: Upload artifact
|
|
35
|
+
uses: actions/upload-pages-artifact@v3
|
|
36
|
+
|
|
37
|
+
deploy:
|
|
38
|
+
environment:
|
|
39
|
+
name: github-pages
|
|
40
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
needs: build
|
|
43
|
+
steps:
|
|
44
|
+
- name: Deploy to GitHub Pages
|
|
45
|
+
id: deployment
|
|
46
|
+
uses: actions/deploy-pages@v4
|
data/.github/workflows/test.yaml
CHANGED
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
|
|
17
17
|
test:
|
|
18
18
|
needs: ruby-versions
|
|
19
|
-
runs-on: ubuntu-
|
|
19
|
+
runs-on: ubuntu-22.04
|
|
20
20
|
strategy:
|
|
21
21
|
fail-fast: false
|
|
22
22
|
matrix:
|
|
@@ -54,9 +54,28 @@ jobs:
|
|
|
54
54
|
- run: flex --help
|
|
55
55
|
- run: bundle install
|
|
56
56
|
- run: bundle exec rspec
|
|
57
|
+
test-c:
|
|
58
|
+
needs: ruby-versions
|
|
59
|
+
runs-on: ubuntu-22.04
|
|
60
|
+
strategy:
|
|
61
|
+
fail-fast: false
|
|
62
|
+
matrix:
|
|
63
|
+
ruby: ['head']
|
|
64
|
+
compiler: ['cc', 'gcc', 'clang']
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
- uses: ruby/setup-ruby@v1
|
|
68
|
+
with:
|
|
69
|
+
ruby-version: ${{ matrix.ruby }}
|
|
70
|
+
bundler-cache: true
|
|
71
|
+
- run: flex --help
|
|
72
|
+
- run: bundle install
|
|
73
|
+
- run: bundle exec rspec
|
|
74
|
+
env:
|
|
75
|
+
COMPILER: ${{ matrix.compiler }}
|
|
57
76
|
test-cpp:
|
|
58
77
|
needs: ruby-versions
|
|
59
|
-
runs-on: ubuntu-
|
|
78
|
+
runs-on: ubuntu-22.04
|
|
60
79
|
strategy:
|
|
61
80
|
fail-fast: false
|
|
62
81
|
matrix:
|
|
@@ -74,7 +93,7 @@ jobs:
|
|
|
74
93
|
env:
|
|
75
94
|
COMPILER: ${{ matrix.compiler }}
|
|
76
95
|
test-memory:
|
|
77
|
-
runs-on: ubuntu-
|
|
96
|
+
runs-on: ubuntu-22.04
|
|
78
97
|
strategy:
|
|
79
98
|
fail-fast: false
|
|
80
99
|
matrix:
|
|
@@ -94,7 +113,7 @@ jobs:
|
|
|
94
113
|
env:
|
|
95
114
|
ENABEL_VALGRIND: 'true'
|
|
96
115
|
check-misc:
|
|
97
|
-
runs-on: ubuntu-
|
|
116
|
+
runs-on: ubuntu-22.04
|
|
98
117
|
strategy:
|
|
99
118
|
matrix:
|
|
100
119
|
ruby: ['head']
|
|
@@ -122,7 +141,7 @@ jobs:
|
|
|
122
141
|
bundle exec rake build:parser
|
|
123
142
|
git diff --color --no-ext-diff --ignore-submodules --exit-code lib/lrama/parser.rb
|
|
124
143
|
steep-check:
|
|
125
|
-
runs-on: ubuntu-
|
|
144
|
+
runs-on: ubuntu-22.04
|
|
126
145
|
strategy:
|
|
127
146
|
fail-fast: false
|
|
128
147
|
matrix:
|
|
@@ -136,10 +155,19 @@ jobs:
|
|
|
136
155
|
ruby-version: ${{ matrix.ruby }}
|
|
137
156
|
bundler-cache: true
|
|
138
157
|
- run: bundle install
|
|
158
|
+
- run: bundle exec rbs-inline --output lib/
|
|
159
|
+
- name: Check for uncommitted changes
|
|
160
|
+
run: |
|
|
161
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
162
|
+
echo "Uncommitted changes detected after running rbs-inline."
|
|
163
|
+
echo "Please run 'bundle rake rbs_inline' and commit the changes generated by rbs-inline." >&2
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|
|
166
|
+
shell: bash
|
|
139
167
|
- run: bundle exec rbs collection install
|
|
140
168
|
- run: bundle exec steep check
|
|
141
169
|
test-ruby:
|
|
142
|
-
runs-on: ubuntu-
|
|
170
|
+
runs-on: ubuntu-22.04
|
|
143
171
|
strategy:
|
|
144
172
|
fail-fast: false
|
|
145
173
|
matrix:
|
|
@@ -184,7 +212,7 @@ jobs:
|
|
|
184
212
|
sudo apt-get install -q -y pkg-config${arch} || :
|
|
185
213
|
- run: sudo apt-get --purge remove bison
|
|
186
214
|
- run: ../autogen.sh
|
|
187
|
-
- run: ../configure -C --disable-install-doc
|
|
215
|
+
- run: ../configure -C --disable-install-doc --with-parser=parse.y
|
|
188
216
|
- run: make
|
|
189
217
|
- run: make test-all RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS"
|
|
190
218
|
env:
|
data/.gitignore
CHANGED
data/.rdoc_options
ADDED
data/Gemfile
CHANGED
|
@@ -7,6 +7,7 @@ gemspec
|
|
|
7
7
|
gem "pry"
|
|
8
8
|
gem "racc", "1.8.1"
|
|
9
9
|
gem "rake"
|
|
10
|
+
gem "rdoc"
|
|
10
11
|
gem "rspec"
|
|
11
12
|
gem "simplecov", require: false
|
|
12
13
|
gem "stackprof", platforms: [:ruby] # stackprof doesn't support Windows
|
|
@@ -15,6 +16,7 @@ gem "memory_profiler"
|
|
|
15
16
|
# Recent steep requires Ruby >= 3.0.0.
|
|
16
17
|
# Then skip install on some CI jobs.
|
|
17
18
|
if !ENV['GITHUB_ACTION'] || ENV['INSTALL_STEEP'] == 'true'
|
|
18
|
-
gem "rbs", "3.
|
|
19
|
-
gem "
|
|
19
|
+
gem "rbs", "3.8.1", require: false
|
|
20
|
+
gem "rbs-inline", require: false
|
|
21
|
+
gem "steep", "1.9.3", require: false
|
|
20
22
|
end
|
data/NEWS.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# NEWS for Lrama
|
|
2
2
|
|
|
3
|
+
## Lrama 0.7.0 (2025-01-21)
|
|
4
|
+
|
|
5
|
+
## [EXPERIMENTAL] Support the generation of the IELR(1) parser described in this paper
|
|
6
|
+
|
|
7
|
+
Support the generation of the IELR(1) parser described in this paper.
|
|
8
|
+
https://www.sciencedirect.com/science/article/pii/S0167642309001191
|
|
9
|
+
|
|
10
|
+
If you use IELR(1) parser, you can write the following directive in your grammar file.
|
|
11
|
+
|
|
12
|
+
```yacc
|
|
13
|
+
%define lr.type ielr
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
But, currently IELR(1) parser is experimental feature. If you find any bugs, please report it to us. Thank you.
|
|
17
|
+
|
|
18
|
+
## Support `-t` option as same as `--debug` option
|
|
19
|
+
|
|
20
|
+
Support to `-t` option as same as `--debug` option.
|
|
21
|
+
These options align with Bison behavior. So same as `--debug` option.
|
|
22
|
+
|
|
23
|
+
## Trace only explicit rules
|
|
24
|
+
|
|
25
|
+
Support to trace only explicit rules.
|
|
26
|
+
If you use `--trace=rules` option, it shows include mid-rule actions. If you want to show only explicit rules, you can use `--trace=only-explicit-rules` option.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
|
|
30
|
+
```yacc
|
|
31
|
+
%{
|
|
32
|
+
%}
|
|
33
|
+
%union {
|
|
34
|
+
int i;
|
|
35
|
+
}
|
|
36
|
+
%token <i> number
|
|
37
|
+
%type <i> program
|
|
38
|
+
%%
|
|
39
|
+
program : number { printf("%d", $1); } number { $$ = $1 + $3; }
|
|
40
|
+
;
|
|
41
|
+
%%
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Result of `--trace=rules`:
|
|
45
|
+
|
|
46
|
+
```console
|
|
47
|
+
$ exe/lrama --trace=rules sample.y
|
|
48
|
+
Grammar rules:
|
|
49
|
+
$accept -> program YYEOF
|
|
50
|
+
$@1 -> ε
|
|
51
|
+
program -> number $@1 number
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Result of `--trace=only-explicit-rules`:
|
|
55
|
+
|
|
56
|
+
```console
|
|
57
|
+
$ exe/lrama --trace=explicit-rules sample.y
|
|
58
|
+
Grammar rules:
|
|
59
|
+
$accept -> program YYEOF
|
|
60
|
+
program -> number number
|
|
61
|
+
```
|
|
62
|
+
|
|
3
63
|
## Lrama 0.6.11 (2024-12-23)
|
|
4
64
|
|
|
5
65
|
### Add support for %type declarations using %nterm in Nonterminal Symbols
|
data/README.md
CHANGED
|
@@ -6,19 +6,32 @@
|
|
|
6
6
|
|
|
7
7
|
Lrama is LALR (1) parser generator written by Ruby. The first goal of this project is providing error tolerant parser for CRuby with minimal changes on CRuby parse.y file.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
- [Features](#features)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Usage](#usage)
|
|
12
|
+
- [Documentation](#documentation)
|
|
13
|
+
- [Versions and Branches](#versions-and-branches)
|
|
14
|
+
- [v0\_7 (`master` branch)](#v0_7-master-branch)
|
|
15
|
+
- [v0\_6 (`lrama_0_6` branch)](#v0_6-lrama_0_6-branch)
|
|
16
|
+
- [v0\_5 (`lrama_0_5` branch)](#v0_5-lrama_0_5-branch)
|
|
17
|
+
- [v0\_4 (`lrama_0_4` branch)](#v0_4-lrama_0_4-branch)
|
|
18
|
+
- [Supported Ruby version](#supported-ruby-version)
|
|
19
|
+
- [Development](#development)
|
|
20
|
+
- [How to generate parser.rb](#how-to-generate-parserrb)
|
|
21
|
+
- [How to Write a Type Signature](#how-to-write-a-type-signature)
|
|
22
|
+
- [Test](#test)
|
|
23
|
+
- [Call-stack Profiling Lrama](#call-stack-profiling-lrama)
|
|
24
|
+
- [1. Create parse.tmp.y in ruby/ruby](#1-create-parsetmpy-in-rubyruby)
|
|
25
|
+
- [2. Enable Profiler](#2-enable-profiler)
|
|
26
|
+
- [3. Run Lrama](#3-run-lrama)
|
|
27
|
+
- [4. Generate Flamegraph](#4-generate-flamegraph)
|
|
28
|
+
- [Memory Profiling Lrama](#memory-profiling-lrama)
|
|
29
|
+
- [1. Create parse.tmp.y in ruby/ruby](#1-create-parsetmpy-in-rubyruby-1)
|
|
30
|
+
- [2. Enable Profiler](#2-enable-profiler-1)
|
|
31
|
+
- [3. Run Lrama](#3-run-lrama-1)
|
|
32
|
+
- [Build Ruby](#build-ruby)
|
|
33
|
+
- [Release flow](#release-flow)
|
|
34
|
+
- [License](#license)
|
|
22
35
|
|
|
23
36
|
## Features
|
|
24
37
|
|
|
@@ -71,11 +84,19 @@ Enter the formula:
|
|
|
71
84
|
=> 9
|
|
72
85
|
```
|
|
73
86
|
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
https://ruby.github.io/lrama/ provides a comprehensive guide to Lrama's features and usage.
|
|
90
|
+
|
|
74
91
|
## Versions and Branches
|
|
75
92
|
|
|
76
|
-
###
|
|
93
|
+
### v0_7 (`master` branch)
|
|
94
|
+
|
|
95
|
+
This branch is for Ruby 3.5. `lrama_0_7` branch is created from this branch, once Ruby 3.5 is released.
|
|
96
|
+
|
|
97
|
+
### v0_6 (`lrama_0_6` branch)
|
|
77
98
|
|
|
78
|
-
This branch is for Ruby 3.4.
|
|
99
|
+
This branch is for Ruby 3.4.
|
|
79
100
|
|
|
80
101
|
### v0_5 (`lrama_0_5` branch)
|
|
81
102
|
|
|
@@ -102,6 +123,14 @@ $ bundle exec rake build:parser
|
|
|
102
123
|
`parser.rb` is generated from `parser.y` by Racc.
|
|
103
124
|
Run the rake command when you update `parser.y` then commit changes of both files.
|
|
104
125
|
|
|
126
|
+
### How to Write a Type Signature
|
|
127
|
+
|
|
128
|
+
We use [Steep](https://github.com/soutaro/steep) for type checking and [rbs-inline](https://github.com/soutaro/rbs-inline) for type declarations.
|
|
129
|
+
|
|
130
|
+
Currently, type signatures are declared in the [sig/lrama](https://github.com/ruby/lrama/blob/master/sig/lrama) directory. However, these files will be replaced with `rbs-inline`. This means type signatures should be written directly in the source code.
|
|
131
|
+
|
|
132
|
+
For guidance on writing type signatures, refer to the [Syntax Guide](https://github.com/soutaro/rbs-inline/wiki/Syntax-guide) in the rbs-inline documentation.
|
|
133
|
+
|
|
105
134
|
### Test
|
|
106
135
|
|
|
107
136
|
Running tests:
|
data/Rakefile
CHANGED
|
@@ -15,9 +15,21 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
|
15
15
|
end
|
|
16
16
|
task :spec => "build:parser"
|
|
17
17
|
|
|
18
|
+
require "rdoc/task"
|
|
19
|
+
RDoc::Task.new do |rdoc|
|
|
20
|
+
rdoc.title = "Lrama Documentation"
|
|
21
|
+
rdoc.main = "Index.md"
|
|
22
|
+
rdoc.rdoc_dir = "_site"
|
|
23
|
+
end
|
|
24
|
+
|
|
18
25
|
desc "steep check"
|
|
19
26
|
task :steep do
|
|
20
27
|
sh "bundle exec steep check"
|
|
21
28
|
end
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
desc "Run rbs-inline"
|
|
31
|
+
task :rbs_inline do
|
|
32
|
+
sh "bundle exec rbs-inline --output lib/"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
task default: %i[spec rbs_inline steep]
|
data/Steepfile
CHANGED
data/doc/Index.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Lrama
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/lrama)
|
|
4
|
+
[](https://github.com/ruby/lrama/actions/workflows/test.yaml)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Lrama is LALR (1) parser generator written by Ruby. The first goal of this project is providing error tolerant parser for CRuby with minimal changes on CRuby parse.y file.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Lrama's installation is simple. You can install it via RubyGems.
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
$ gem install lrama
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
From source codes, you can install it as follows:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
$ cd "$(lrama root)"
|
|
23
|
+
$ bundle install
|
|
24
|
+
$ bundle exec rake install
|
|
25
|
+
$ bundle exec lrama --version
|
|
26
|
+
lrama 0.7.0
|
|
27
|
+
```
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Lrama is a command line tool. You can generate a parser from a grammar file by running `lrama` command.
|
|
31
|
+
|
|
32
|
+
```shell
|
|
33
|
+
# "y.tab.c" and "y.tab.h" are generated
|
|
34
|
+
$ lrama -d sample/parse.y
|
|
35
|
+
```
|
|
36
|
+
Specify the output file with `-o` option. The following example generates "calc.c" and "calc.h".
|
|
37
|
+
|
|
38
|
+
```shell
|
|
39
|
+
# "calc", "calc.c", and "calc.h" are generated
|
|
40
|
+
$ lrama -d sample/calc.y -o calc.c && gcc -Wall calc.c -o calc && ./calc
|
|
41
|
+
Enter the formula:
|
|
42
|
+
1
|
|
43
|
+
=> 1
|
|
44
|
+
1+2*3
|
|
45
|
+
=> 7
|
|
46
|
+
(1+2)*3
|
|
47
|
+
=> 9
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Supported Ruby version
|
|
51
|
+
|
|
52
|
+
Lrama is executed with BASERUBY when building ruby from source code. Therefore Lrama needs to support BASERUBY, currently 2.5, or later version.
|
|
53
|
+
|
|
54
|
+
This also requires Lrama to be able to run with only default gems because BASERUBY runs with `--disable=gems` option.
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
See [LEGAL.md](https://github.com/ruby/lrama/blob/master/LEGAL.md) file.
|
data/lib/lrama/bitmap.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Lrama
|
|
4
5
|
module Bitmap
|
|
6
|
+
# @rbs (Array[Integer] ary) -> Integer
|
|
5
7
|
def self.from_array(ary)
|
|
6
8
|
bit = 0
|
|
7
9
|
|
|
@@ -12,6 +14,7 @@ module Lrama
|
|
|
12
14
|
bit
|
|
13
15
|
end
|
|
14
16
|
|
|
17
|
+
# @rbs (Integer int) -> Array[Integer]
|
|
15
18
|
def self.to_array(int)
|
|
16
19
|
a = [] #: Array[Integer]
|
|
17
20
|
i = 0
|
data/lib/lrama/command.rb
CHANGED
|
@@ -19,7 +19,7 @@ module Lrama
|
|
|
19
19
|
text = options.y.read
|
|
20
20
|
options.y.close if options.y != STDIN
|
|
21
21
|
begin
|
|
22
|
-
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse
|
|
22
|
+
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug, options.define).parse
|
|
23
23
|
unless grammar.no_stdlib
|
|
24
24
|
stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
|
|
25
25
|
grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
|
|
@@ -34,6 +34,7 @@ module Lrama
|
|
|
34
34
|
end
|
|
35
35
|
states = Lrama::States.new(grammar, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
|
|
36
36
|
states.compute
|
|
37
|
+
states.compute_ielr if grammar.ielr_defined?
|
|
37
38
|
context = Lrama::Context.new(states)
|
|
38
39
|
|
|
39
40
|
if options.report_file
|
data/lib/lrama/digraph.rb
CHANGED
|
@@ -1,23 +1,52 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Lrama
|
|
4
5
|
# Algorithm Digraph of https://dl.acm.org/doi/pdf/10.1145/69622.357187 (P. 625)
|
|
6
|
+
#
|
|
7
|
+
# @rbs generic X < Object -- Type of a member of `sets`
|
|
8
|
+
# @rbs generic Y < _Or -- Type of sets assigned to a member of `sets`
|
|
5
9
|
class Digraph
|
|
10
|
+
# TODO: rbs-inline 0.10.0 doesn't support instance variables.
|
|
11
|
+
# Move these type declarations above instance variable definitions, once it's supported.
|
|
12
|
+
#
|
|
13
|
+
# @rbs!
|
|
14
|
+
# interface _Or
|
|
15
|
+
# def |: (self) -> self
|
|
16
|
+
# end
|
|
17
|
+
# @sets: Array[X]
|
|
18
|
+
# @relation: Hash[X, Array[X]]
|
|
19
|
+
# @base_function: Hash[X, Y]
|
|
20
|
+
# @stack: Array[X]
|
|
21
|
+
# @h: Hash[X, (Integer|Float)?]
|
|
22
|
+
# @result: Hash[X, Y]
|
|
23
|
+
|
|
24
|
+
# @rbs sets: Array[X]
|
|
25
|
+
# @rbs relation: Hash[X, Array[X]]
|
|
26
|
+
# @rbs base_function: Hash[X, Y]
|
|
27
|
+
# @rbs return: void
|
|
6
28
|
def initialize(sets, relation, base_function)
|
|
29
|
+
|
|
7
30
|
# X in the paper
|
|
8
31
|
@sets = sets
|
|
32
|
+
|
|
9
33
|
# R in the paper
|
|
10
34
|
@relation = relation
|
|
35
|
+
|
|
11
36
|
# F' in the paper
|
|
12
37
|
@base_function = base_function
|
|
38
|
+
|
|
13
39
|
# S in the paper
|
|
14
40
|
@stack = []
|
|
41
|
+
|
|
15
42
|
# N in the paper
|
|
16
43
|
@h = Hash.new(0)
|
|
44
|
+
|
|
17
45
|
# F in the paper
|
|
18
46
|
@result = {}
|
|
19
47
|
end
|
|
20
48
|
|
|
49
|
+
# @rbs () -> Hash[X, Y]
|
|
21
50
|
def compute
|
|
22
51
|
@sets.each do |x|
|
|
23
52
|
next if @h[x] != 0
|
|
@@ -29,6 +58,7 @@ module Lrama
|
|
|
29
58
|
|
|
30
59
|
private
|
|
31
60
|
|
|
61
|
+
# @rbs (X x) -> void
|
|
32
62
|
def traverse(x)
|
|
33
63
|
@stack.push(x)
|
|
34
64
|
d = @stack.count
|
|
@@ -1,34 +1,66 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Lrama
|
|
4
5
|
class Grammar
|
|
5
6
|
class Binding
|
|
6
|
-
|
|
7
|
+
# @rbs @actual_args: Array[Lexer::Token]
|
|
8
|
+
# @rbs @param_to_arg: Hash[String, Lexer::Token]
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
# @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> void
|
|
11
|
+
def initialize(params, actual_args)
|
|
10
12
|
@actual_args = actual_args
|
|
11
|
-
@
|
|
12
|
-
[param.s_value, arg]
|
|
13
|
-
end.to_h
|
|
13
|
+
@param_to_arg = map_params_to_args(params, @actual_args)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Lrama::Lexer::Token::InstantiateRule.new(
|
|
16
|
+
# @rbs (Lexer::Token sym) -> Lexer::Token
|
|
17
|
+
def resolve_symbol(sym)
|
|
18
|
+
if sym.is_a?(Lexer::Token::InstantiateRule)
|
|
19
|
+
Lrama::Lexer::Token::InstantiateRule.new(
|
|
20
|
+
s_value: sym.s_value, location: sym.location, args: resolved_args(sym), lhs_tag: sym.lhs_tag
|
|
21
|
+
)
|
|
20
22
|
else
|
|
21
|
-
|
|
23
|
+
param_to_arg(sym)
|
|
22
24
|
end
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
# @rbs (Lexer::Token::InstantiateRule token) -> String
|
|
28
|
+
def concatenated_args_str(token)
|
|
29
|
+
"#{token.rule_name}_#{token_to_args_s_values(token).join('_')}"
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
private
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
# @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> Hash[String, Lexer::Token]
|
|
35
|
+
def map_params_to_args(params, actual_args)
|
|
36
|
+
params.zip(actual_args).map do |param, arg|
|
|
37
|
+
[param.s_value, arg]
|
|
38
|
+
end.to_h
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @rbs (Lexer::Token::InstantiateRule sym) -> Array[Lexer::Token]
|
|
42
|
+
def resolved_args(sym)
|
|
43
|
+
sym.args.map { |arg| resolve_symbol(arg) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @rbs (Lexer::Token sym) -> Lexer::Token
|
|
47
|
+
def param_to_arg(sym)
|
|
48
|
+
if (arg = @param_to_arg[sym.s_value].dup)
|
|
49
|
+
arg.alias_name = sym.alias_name
|
|
50
|
+
end
|
|
51
|
+
arg || sym
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @rbs (Lexer::Token::InstantiateRule token) -> Array[String]
|
|
55
|
+
def token_to_args_s_values(token)
|
|
56
|
+
token.args.flat_map do |arg|
|
|
57
|
+
resolved = resolve_symbol(arg)
|
|
58
|
+
if resolved.is_a?(Lexer::Token::InstantiateRule)
|
|
59
|
+
[resolved.s_value] + resolved.args.map(&:s_value)
|
|
60
|
+
else
|
|
61
|
+
[resolved.s_value]
|
|
62
|
+
end
|
|
30
63
|
end
|
|
31
|
-
arg
|
|
32
64
|
end
|
|
33
65
|
end
|
|
34
66
|
end
|
data/lib/lrama/grammar/rule.rb
CHANGED
|
@@ -21,6 +21,14 @@ module Lrama
|
|
|
21
21
|
def display_name
|
|
22
22
|
l = lhs.id.s_value
|
|
23
23
|
r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(" ")
|
|
24
|
+
"#{l} -> #{r}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def display_name_without_action
|
|
28
|
+
l = lhs.id.s_value
|
|
29
|
+
r = empty_rule? ? "ε" : rhs.map do |r|
|
|
30
|
+
r.id.s_value if r.first_set.any?
|
|
31
|
+
end.compact.join(" ")
|
|
24
32
|
|
|
25
33
|
"#{l} -> #{r}"
|
|
26
34
|
end
|
|
@@ -73,7 +73,7 @@ module Lrama
|
|
|
73
73
|
inline_rule.rhs_list.each do |inline_rhs|
|
|
74
74
|
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: lhs_tag)
|
|
75
75
|
if token.is_a?(Lexer::Token::InstantiateRule)
|
|
76
|
-
resolve_inline_rhs(rule_builder, inline_rhs, i, Binding.new(inline_rule, token.args))
|
|
76
|
+
resolve_inline_rhs(rule_builder, inline_rhs, i, Binding.new(inline_rule.parameters, token.args))
|
|
77
77
|
else
|
|
78
78
|
resolve_inline_rhs(rule_builder, inline_rhs, i)
|
|
79
79
|
end
|
|
@@ -135,8 +135,8 @@ module Lrama
|
|
|
135
135
|
parameterizing_rule = @parameterizing_rule_resolver.find_rule(token)
|
|
136
136
|
raise "Unexpected token. #{token}" unless parameterizing_rule
|
|
137
137
|
|
|
138
|
-
bindings = Binding.new(parameterizing_rule, token.args)
|
|
139
|
-
lhs_s_value =
|
|
138
|
+
bindings = Binding.new(parameterizing_rule.parameters, token.args)
|
|
139
|
+
lhs_s_value = bindings.concatenated_args_str(token)
|
|
140
140
|
if (created_lhs = @parameterizing_rule_resolver.created_lhs(lhs_s_value))
|
|
141
141
|
@replaced_rhs << created_lhs
|
|
142
142
|
else
|
|
@@ -174,18 +174,6 @@ module Lrama
|
|
|
174
174
|
end
|
|
175
175
|
end
|
|
176
176
|
|
|
177
|
-
def lhs_s_value(token, bindings)
|
|
178
|
-
s_values = token.args.map do |arg|
|
|
179
|
-
resolved = bindings.resolve_symbol(arg)
|
|
180
|
-
if resolved.is_a?(Lexer::Token::InstantiateRule)
|
|
181
|
-
[resolved.s_value, resolved.args.map(&:s_value)]
|
|
182
|
-
else
|
|
183
|
-
resolved.s_value
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
"#{token.rule_name}_#{s_values.join('_')}"
|
|
187
|
-
end
|
|
188
|
-
|
|
189
177
|
def resolve_inline_rhs(rule_builder, inline_rhs, index, bindings = nil)
|
|
190
178
|
rhs.each_with_index do |token, i|
|
|
191
179
|
if index == i
|