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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gh-pages.yml +46 -0
  3. data/.github/workflows/test.yaml +35 -7
  4. data/.gitignore +1 -0
  5. data/.rdoc_options +2 -0
  6. data/Gemfile +4 -2
  7. data/NEWS.md +60 -0
  8. data/README.md +44 -15
  9. data/Rakefile +13 -1
  10. data/Steepfile +2 -0
  11. data/doc/Index.md +58 -0
  12. data/lib/lrama/bitmap.rb +3 -0
  13. data/lib/lrama/command.rb +2 -1
  14. data/lib/lrama/digraph.rb +30 -0
  15. data/lib/lrama/grammar/binding.rb +47 -15
  16. data/lib/lrama/grammar/rule.rb +8 -0
  17. data/lib/lrama/grammar/rule_builder.rb +3 -15
  18. data/lib/lrama/grammar.rb +8 -3
  19. data/lib/lrama/lexer/grammar_file.rb +8 -1
  20. data/lib/lrama/lexer/location.rb +17 -1
  21. data/lib/lrama/lexer/token/char.rb +1 -0
  22. data/lib/lrama/lexer/token/ident.rb +1 -0
  23. data/lib/lrama/lexer/token/instantiate_rule.rb +6 -1
  24. data/lib/lrama/lexer/token/tag.rb +3 -1
  25. data/lib/lrama/lexer/token/user_code.rb +5 -1
  26. data/lib/lrama/lexer/token.rb +14 -2
  27. data/lib/lrama/lexer.rb +4 -5
  28. data/lib/lrama/logger.rb +4 -0
  29. data/lib/lrama/option_parser.rb +10 -8
  30. data/lib/lrama/options.rb +2 -1
  31. data/lib/lrama/parser.rb +10 -4
  32. data/lib/lrama/state.rb +288 -1
  33. data/lib/lrama/states/item.rb +8 -0
  34. data/lib/lrama/states.rb +69 -2
  35. data/lib/lrama/trace_reporter.rb +17 -2
  36. data/lib/lrama/version.rb +1 -1
  37. data/lrama.gemspec +1 -1
  38. data/parser.y +4 -3
  39. data/rbs_collection.lock.yaml +3 -3
  40. data/sig/generated/lrama/bitmap.rbs +11 -0
  41. data/sig/generated/lrama/digraph.rbs +39 -0
  42. data/sig/generated/lrama/grammar/binding.rbs +34 -0
  43. data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
  44. data/sig/generated/lrama/lexer/location.rbs +52 -0
  45. data/sig/{lrama → generated/lrama}/lexer/token/char.rbs +2 -0
  46. data/sig/{lrama → generated/lrama}/lexer/token/ident.rbs +2 -0
  47. data/sig/{lrama → generated/lrama}/lexer/token/instantiate_rule.rbs +8 -0
  48. data/sig/{lrama → generated/lrama}/lexer/token/tag.rbs +3 -0
  49. data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +6 -1
  50. data/sig/{lrama → generated/lrama}/lexer/token.rbs +26 -3
  51. data/sig/generated/lrama/logger.rbs +14 -0
  52. data/sig/generated/lrama/trace_reporter.rbs +25 -0
  53. data/sig/lrama/grammar/rule_builder.rbs +0 -1
  54. data/sig/lrama/options.rbs +1 -0
  55. metadata +19 -14
  56. data/sig/lrama/bitmap.rbs +0 -7
  57. data/sig/lrama/digraph.rbs +0 -23
  58. data/sig/lrama/grammar/binding.rbs +0 -19
  59. data/sig/lrama/lexer/grammar_file.rbs +0 -17
  60. data/sig/lrama/lexer/location.rbs +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d566a5097f0fd579e70f94769cca4e68a8f0e810e10cd55556583b1c2653945
4
- data.tar.gz: e5ab505df1a8fffe46a9f526456b593db786f36f0e998e7e3acbf5f68b76d9a9
3
+ metadata.gz: 9c967547ee9de2d87e1e275bf5d9b1f525b7040f110ee41b9144b163923a3dd6
4
+ data.tar.gz: f9ada41c05e186245e11dfca1dc31da2f2bf8987090b91ed5312369ad1306e64
5
5
  SHA512:
6
- metadata.gz: 753a7b6f0781f6b0bd2db8c98ef0e6171496d6fd8a2a16762b67dc471e34b4118b4439b89facc1915a364d4c4823edaef464d947cbda3d913ebd8eff87d91b76
7
- data.tar.gz: 7f953657c7050c7d527bf190d284e5b56b3df5b92c2034d5f4425f73be1e21208d1869a4ffe6c9091b4adf79671e71865000797ec2d7ed1ad66cfe5d1846cd7b
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
@@ -16,7 +16,7 @@ jobs:
16
16
 
17
17
  test:
18
18
  needs: ruby-versions
19
- runs-on: ubuntu-20.04
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-20.04
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-20.04
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-20.04
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-20.04
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-20.04
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
@@ -10,3 +10,4 @@
10
10
  /tmp/
11
11
  /vendor/bundle
12
12
  /.idea/
13
+ _site/
data/.rdoc_options ADDED
@@ -0,0 +1,2 @@
1
+ page_dir: doc
2
+ warn_missing_rdoc_ref: true
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.7.0", require: false
19
- gem "steep", "1.9.1", require: false
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
- * [Features](#features)
10
- * [Installation](#installation)
11
- * [Usage](#usage)
12
- * [Versions and Branches](#versions-and-branches)
13
- * [Supported Ruby version](#supported-ruby-version)
14
- * [Development](#development)
15
- * [How to generate parser.rb](#how-to-generate-parserrb)
16
- * [Test](#test)
17
- * [Call-stack Profiling Lrama](#call-stack-profiling-lrama)
18
- * [Memory Profiling Lrama](#memory-profiling-lrama)
19
- * [Build Ruby](#build-ruby)
20
- * [Release flow](#release-flow)
21
- * [License](#license)
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
- ### v0_6 (`master` branch)
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. `lrama_0_6` branch is created from this branch, once Ruby 3.4 is released.
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
- task default: %i[spec steep]
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
@@ -17,6 +17,8 @@ target :lib do
17
17
  check "lib/lrama/counterexamples.rb"
18
18
  check "lib/lrama/digraph.rb"
19
19
  check "lib/lrama/grammar.rb"
20
+ check "lib/lrama/logger.rb"
20
21
  check "lib/lrama/options.rb"
22
+ check "lib/lrama/trace_reporter.rb"
21
23
  check "lib/lrama/warning.rb"
22
24
  end
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
- attr_reader :actual_args, :count
7
+ # @rbs @actual_args: Array[Lexer::Token]
8
+ # @rbs @param_to_arg: Hash[String, Lexer::Token]
7
9
 
8
- def initialize(parameterizing_rule, actual_args)
9
- @parameters = parameterizing_rule.parameters
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
- @parameter_to_arg = @parameters.zip(actual_args).map do |param, arg|
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
- def resolve_symbol(symbol)
17
- if symbol.is_a?(Lexer::Token::InstantiateRule)
18
- resolved_args = symbol.args.map { |arg| resolve_symbol(arg) }
19
- Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag)
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
- parameter_to_arg(symbol) || symbol
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
- def parameter_to_arg(symbol)
28
- if (arg = @parameter_to_arg[symbol.s_value].dup)
29
- arg.alias_name = symbol.alias_name
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
@@ -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 = lhs_s_value(token, bindings)
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