lrama 0.6.11 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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