lrama 0.6.11 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/lrama.svg)](https://badge.fury.io/rb/lrama)
|
4
|
+
[![build](https://github.com/ruby/lrama/actions/workflows/test.yaml/badge.svg)](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
|