lrama 0.7.0 → 0.7.1
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/.gitattributes +2 -0
- data/.github/workflows/codespell.yaml +1 -1
- data/.github/workflows/gh-pages.yml +5 -6
- data/.github/workflows/test.yaml +25 -14
- data/Gemfile +4 -3
- data/NEWS.md +370 -35
- data/README.md +7 -88
- data/Rakefile +3 -2
- data/Steepfile +11 -5
- data/doc/Index.md +1 -1
- data/doc/development/compressed_state_table/parser.rb +2 -0
- data/doc/development/profiling.md +44 -0
- data/exe/lrama +1 -1
- data/lib/lrama/bitmap.rb +18 -5
- data/lib/lrama/command.rb +95 -43
- data/lib/lrama/context.rb +22 -24
- data/lib/lrama/counterexamples/derivation.rb +14 -4
- data/lib/lrama/counterexamples/example.rb +47 -22
- data/lib/lrama/counterexamples/node.rb +30 -0
- data/lib/lrama/counterexamples/path.rb +12 -14
- data/lib/lrama/counterexamples/state_item.rb +24 -1
- data/lib/lrama/counterexamples/triple.rb +27 -9
- data/lib/lrama/counterexamples.rb +216 -88
- data/lib/lrama/diagram.rb +77 -0
- data/lib/lrama/digraph.rb +28 -7
- data/lib/lrama/erb.rb +29 -0
- data/lib/lrama/grammar/auxiliary.rb +6 -1
- data/lib/lrama/grammar/binding.rb +37 -25
- data/lib/lrama/grammar/code/destructor_code.rb +11 -0
- data/lib/lrama/grammar/code/initial_action_code.rb +3 -0
- data/lib/lrama/grammar/code/no_reference_code.rb +3 -0
- data/lib/lrama/grammar/code/printer_code.rb +11 -0
- data/lib/lrama/grammar/code/rule_action.rb +17 -0
- data/lib/lrama/grammar/code.rb +16 -1
- data/lib/lrama/grammar/counter.rb +10 -0
- data/lib/lrama/grammar/destructor.rb +14 -1
- data/lib/lrama/grammar/error_token.rb +14 -1
- data/lib/lrama/grammar/inline/resolver.rb +80 -0
- data/lib/lrama/grammar/inline.rb +3 -0
- data/lib/lrama/grammar/{parameterizing_rule → parameterized}/resolver.rb +19 -8
- data/lib/lrama/grammar/{parameterizing_rule → parameterized}/rhs.rb +7 -2
- data/lib/lrama/grammar/parameterized/rule.rb +36 -0
- data/lib/lrama/grammar/parameterized.rb +5 -0
- data/lib/lrama/grammar/percent_code.rb +12 -1
- data/lib/lrama/grammar/precedence.rb +43 -1
- data/lib/lrama/grammar/printer.rb +9 -0
- data/lib/lrama/grammar/reference.rb +13 -0
- data/lib/lrama/grammar/rule.rb +61 -1
- data/lib/lrama/grammar/rule_builder.rb +84 -69
- data/lib/lrama/grammar/stdlib.y +68 -48
- data/lib/lrama/grammar/symbol.rb +63 -19
- data/lib/lrama/grammar/symbols/resolver.rb +64 -3
- data/lib/lrama/grammar/type.rb +13 -1
- data/lib/lrama/grammar/union.rb +12 -1
- data/lib/lrama/grammar.rb +231 -35
- data/lib/lrama/lexer/location.rb +25 -8
- data/lib/lrama/lexer/token/base.rb +73 -0
- data/lib/lrama/lexer/token/char.rb +15 -2
- data/lib/lrama/lexer/token/empty.rb +14 -0
- data/lib/lrama/lexer/token/ident.rb +2 -2
- data/lib/lrama/lexer/token/instantiate_rule.rb +4 -4
- data/lib/lrama/lexer/token/int.rb +14 -0
- data/lib/lrama/lexer/token/str.rb +11 -0
- data/lib/lrama/lexer/token/tag.rb +2 -2
- data/lib/lrama/lexer/token/token.rb +11 -0
- data/lib/lrama/lexer/token/user_code.rb +63 -37
- data/lib/lrama/lexer/token.rb +6 -56
- data/lib/lrama/lexer.rb +51 -23
- data/lib/lrama/logger.rb +12 -2
- data/lib/lrama/option_parser.rb +63 -9
- data/lib/lrama/options.rb +25 -7
- data/lib/lrama/output.rb +4 -11
- data/lib/lrama/parser.rb +854 -723
- data/lib/lrama/reporter/conflicts.rb +44 -0
- data/lib/lrama/reporter/grammar.rb +39 -0
- data/lib/lrama/reporter/precedences.rb +54 -0
- data/lib/lrama/reporter/profile/call_stack.rb +45 -0
- data/lib/lrama/reporter/profile/memory.rb +44 -0
- data/lib/lrama/reporter/profile.rb +4 -0
- data/lib/lrama/reporter/rules.rb +43 -0
- data/lib/lrama/reporter/states.rb +387 -0
- data/lib/lrama/reporter/terms.rb +44 -0
- data/lib/lrama/reporter.rb +39 -0
- data/lib/lrama/state/action/goto.rb +33 -0
- data/lib/lrama/state/action/reduce.rb +71 -0
- data/lib/lrama/state/action/shift.rb +39 -0
- data/lib/lrama/state/action.rb +5 -0
- data/lib/lrama/state/inadequacy_annotation.rb +140 -0
- data/lib/lrama/{states → state}/item.rb +33 -4
- data/lib/lrama/state/reduce_reduce_conflict.rb +14 -1
- data/lib/lrama/state/resolved_conflict.rb +38 -4
- data/lib/lrama/state/shift_reduce_conflict.rb +14 -1
- data/lib/lrama/state.rb +301 -200
- data/lib/lrama/states.rb +447 -175
- data/lib/lrama/tracer/actions.rb +22 -0
- data/lib/lrama/tracer/closure.rb +30 -0
- data/lib/lrama/tracer/duration.rb +38 -0
- data/lib/lrama/tracer/only_explicit_rules.rb +24 -0
- data/lib/lrama/tracer/rules.rb +23 -0
- data/lib/lrama/tracer/state.rb +33 -0
- data/lib/lrama/tracer.rb +51 -0
- data/lib/lrama/version.rb +2 -1
- data/lib/lrama/warnings/conflicts.rb +27 -0
- data/lib/lrama/warnings/implicit_empty.rb +29 -0
- data/lib/lrama/warnings/name_conflicts.rb +63 -0
- data/lib/lrama/warnings/redefined_rules.rb +23 -0
- data/lib/lrama/warnings/required.rb +23 -0
- data/lib/lrama/warnings/useless_precedence.rb +25 -0
- data/lib/lrama/warnings.rb +33 -0
- data/lib/lrama.rb +5 -5
- data/parser.y +495 -404
- data/rbs_collection.lock.yaml +27 -3
- data/rbs_collection.yaml +2 -0
- data/sig/generated/lrama/bitmap.rbs +12 -4
- data/sig/generated/lrama/counterexamples/derivation.rbs +36 -0
- data/sig/generated/lrama/counterexamples/example.rbs +58 -0
- data/sig/generated/lrama/counterexamples/node.rbs +18 -0
- data/sig/generated/lrama/counterexamples/path.rbs +23 -0
- data/sig/generated/lrama/counterexamples/state_item.rbs +19 -0
- data/sig/generated/lrama/counterexamples/triple.rbs +32 -0
- data/sig/generated/lrama/counterexamples.rbs +98 -0
- data/sig/generated/lrama/diagram.rbs +34 -0
- data/sig/generated/lrama/digraph.rbs +26 -6
- data/sig/generated/lrama/erb.rbs +14 -0
- data/sig/generated/lrama/grammar/auxiliary.rbs +16 -0
- data/sig/generated/lrama/grammar/binding.rbs +18 -12
- data/sig/generated/lrama/grammar/code/destructor_code.rbs +26 -0
- data/sig/{lrama → generated/lrama}/grammar/code/initial_action_code.rbs +6 -0
- data/sig/{lrama → generated/lrama}/grammar/code/no_reference_code.rbs +6 -0
- data/sig/generated/lrama/grammar/code/printer_code.rbs +26 -0
- data/sig/generated/lrama/grammar/code/rule_action.rbs +63 -0
- data/sig/generated/lrama/grammar/code.rbs +38 -0
- data/sig/{lrama → generated/lrama}/grammar/counter.rbs +4 -0
- data/sig/generated/lrama/grammar/destructor.rbs +19 -0
- data/sig/generated/lrama/grammar/error_token.rbs +19 -0
- data/sig/generated/lrama/grammar/inline/resolver.rbs +26 -0
- data/sig/generated/lrama/grammar/parameterized/resolver.rbs +42 -0
- data/sig/generated/lrama/grammar/parameterized/rhs.rbs +21 -0
- data/sig/generated/lrama/grammar/parameterized/rule.rbs +28 -0
- data/sig/{lrama → generated/lrama}/grammar/percent_code.rbs +8 -0
- data/sig/generated/lrama/grammar/precedence.rbs +45 -0
- data/sig/{lrama/grammar/error_token.rbs → generated/lrama/grammar/printer.rbs} +8 -3
- data/sig/generated/lrama/grammar/reference.rbs +31 -0
- data/sig/generated/lrama/grammar/rule.rbs +83 -0
- data/sig/generated/lrama/grammar/rule_builder.rbs +91 -0
- data/sig/generated/lrama/grammar/symbol.rbs +89 -0
- data/sig/generated/lrama/grammar/symbols/resolver.rbs +131 -0
- data/sig/generated/lrama/grammar/type.rbs +21 -0
- data/sig/generated/lrama/grammar/union.rbs +17 -0
- data/sig/generated/lrama/grammar.rbs +289 -0
- data/sig/generated/lrama/lexer/location.rbs +12 -3
- data/sig/generated/lrama/lexer/token/base.rbs +53 -0
- data/sig/generated/lrama/lexer/token/char.rbs +9 -2
- data/sig/generated/lrama/lexer/token/empty.rbs +11 -0
- data/sig/generated/lrama/lexer/token/ident.rbs +2 -2
- data/sig/generated/lrama/lexer/token/instantiate_rule.rbs +5 -5
- data/sig/generated/lrama/lexer/token/int.rbs +13 -0
- data/sig/generated/lrama/lexer/token/str.rbs +10 -0
- data/sig/generated/lrama/lexer/token/tag.rbs +2 -2
- data/sig/generated/lrama/lexer/token/token.rbs +10 -0
- data/sig/generated/lrama/lexer/token/user_code.rbs +2 -2
- data/sig/generated/lrama/lexer/token.rbs +1 -39
- data/sig/generated/lrama/lexer.rbs +54 -0
- data/sig/generated/lrama/logger.rbs +6 -0
- data/sig/generated/lrama/option_parser.rbs +52 -0
- data/sig/{lrama → generated/lrama}/options.rbs +27 -3
- data/sig/generated/lrama/reporter/conflicts.rbs +18 -0
- data/sig/generated/lrama/reporter/grammar.rbs +13 -0
- data/sig/generated/lrama/reporter/precedences.rbs +15 -0
- data/sig/generated/lrama/reporter/profile/call_stack.rbs +19 -0
- data/sig/generated/lrama/reporter/profile/memory.rbs +19 -0
- data/sig/generated/lrama/reporter/rules.rbs +13 -0
- data/sig/generated/lrama/reporter/states.rbs +69 -0
- data/sig/generated/lrama/reporter/terms.rbs +13 -0
- data/sig/generated/lrama/reporter.rbs +13 -0
- data/sig/generated/lrama/state/action/goto.rbs +28 -0
- data/sig/generated/lrama/state/action/reduce.rbs +49 -0
- data/sig/generated/lrama/state/action/shift.rbs +33 -0
- data/sig/generated/lrama/state/inadequacy_annotation.rbs +45 -0
- data/sig/generated/lrama/state/item.rbs +75 -0
- data/sig/generated/lrama/state/reduce_reduce_conflict.rbs +19 -0
- data/sig/generated/lrama/state/resolved_conflict.rbs +38 -0
- data/sig/generated/lrama/state/shift_reduce_conflict.rbs +19 -0
- data/sig/generated/lrama/state.rbs +231 -0
- data/sig/generated/lrama/states.rbs +215 -0
- data/sig/generated/lrama/tracer/actions.rbs +13 -0
- data/sig/generated/lrama/tracer/closure.rbs +13 -0
- data/sig/generated/lrama/tracer/duration.rbs +18 -0
- data/sig/generated/lrama/tracer/only_explicit_rules.rbs +13 -0
- data/sig/generated/lrama/tracer/rules.rbs +13 -0
- data/sig/generated/lrama/tracer/state.rbs +16 -0
- data/sig/generated/lrama/tracer.rbs +23 -0
- data/sig/generated/lrama/version.rbs +5 -0
- data/sig/generated/lrama/warnings/conflicts.rbs +13 -0
- data/sig/generated/lrama/warnings/implicit_empty.rbs +17 -0
- data/sig/generated/lrama/warnings/name_conflicts.rbs +31 -0
- data/sig/generated/lrama/warnings/redefined_rules.rbs +13 -0
- data/sig/generated/lrama/warnings/required.rbs +13 -0
- data/sig/generated/lrama/warnings/useless_precedence.rbs +13 -0
- data/sig/generated/lrama/warnings.rbs +11 -0
- data/sig/railroad_diagrams/railroad_diagrams.rbs +16 -0
- data/template/bison/_yacc.h +8 -0
- data/template/diagram/diagram.html +102 -0
- metadata +126 -66
- data/lib/lrama/counterexamples/production_path.rb +0 -19
- data/lib/lrama/counterexamples/start_path.rb +0 -23
- data/lib/lrama/counterexamples/transition_path.rb +0 -19
- data/lib/lrama/diagnostics.rb +0 -36
- data/lib/lrama/grammar/parameterizing_rule/rule.rb +0 -24
- data/lib/lrama/grammar/parameterizing_rule.rb +0 -5
- data/lib/lrama/grammar_validator.rb +0 -37
- data/lib/lrama/report/duration.rb +0 -27
- data/lib/lrama/report/profile.rb +0 -16
- data/lib/lrama/report.rb +0 -4
- data/lib/lrama/state/reduce.rb +0 -37
- data/lib/lrama/state/shift.rb +0 -15
- data/lib/lrama/states_reporter.rb +0 -362
- data/lib/lrama/trace_reporter.rb +0 -45
- data/sig/generated/lrama/trace_reporter.rbs +0 -25
- data/sig/lrama/counterexamples/derivation.rbs +0 -33
- data/sig/lrama/counterexamples/example.rbs +0 -45
- data/sig/lrama/counterexamples/path.rbs +0 -21
- data/sig/lrama/counterexamples/production_path.rbs +0 -11
- data/sig/lrama/counterexamples/start_path.rbs +0 -13
- data/sig/lrama/counterexamples/state_item.rbs +0 -10
- data/sig/lrama/counterexamples/transition_path.rbs +0 -11
- data/sig/lrama/counterexamples/triple.rbs +0 -20
- data/sig/lrama/counterexamples.rbs +0 -29
- data/sig/lrama/grammar/auxiliary.rbs +0 -10
- data/sig/lrama/grammar/code/destructor_code.rbs +0 -14
- data/sig/lrama/grammar/code/printer_code.rbs +0 -14
- data/sig/lrama/grammar/code/rule_action.rbs +0 -19
- data/sig/lrama/grammar/code.rbs +0 -24
- data/sig/lrama/grammar/destructor.rbs +0 -13
- data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +0 -24
- data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +0 -14
- data/sig/lrama/grammar/parameterizing_rule/rule.rbs +0 -16
- data/sig/lrama/grammar/parameterizing_rule.rbs +0 -6
- data/sig/lrama/grammar/precedence.rbs +0 -13
- data/sig/lrama/grammar/printer.rbs +0 -13
- data/sig/lrama/grammar/reference.rbs +0 -22
- data/sig/lrama/grammar/rule.rbs +0 -45
- data/sig/lrama/grammar/rule_builder.rbs +0 -47
- data/sig/lrama/grammar/symbol.rbs +0 -38
- data/sig/lrama/grammar/symbols/resolver.rbs +0 -60
- data/sig/lrama/grammar/type.rbs +0 -11
- data/sig/lrama/grammar/union.rbs +0 -12
- data/sig/lrama/grammar.rbs +0 -108
- data/sig/lrama/report/duration.rbs +0 -11
- data/sig/lrama/report/profile.rbs +0 -7
- data/sig/lrama/state/reduce.rbs +0 -20
- data/sig/lrama/state/reduce_reduce_conflict.rbs +0 -13
- data/sig/lrama/state/resolved_conflict.rbs +0 -14
- data/sig/lrama/state/shift.rbs +0 -14
- data/sig/lrama/state/shift_reduce_conflict.rbs +0 -13
- data/sig/lrama/state.rbs +0 -79
- data/sig/lrama/states/item.rbs +0 -30
- data/sig/lrama/states.rbs +0 -101
- data/sig/lrama/warning.rbs +0 -16
data/Rakefile
CHANGED
|
@@ -5,7 +5,7 @@ require "bundler/gem_tasks"
|
|
|
5
5
|
namespace "build" do
|
|
6
6
|
desc "build parser from parser.y"
|
|
7
7
|
task :parser do
|
|
8
|
-
sh "bundle exec racc parser.y --embedded -o lib/lrama/parser.rb -t --log-file=parser.output"
|
|
8
|
+
sh "bundle exec racc parser.y --embedded --frozen -o lib/lrama/parser.rb -t --log-file=parser.output"
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -26,10 +26,11 @@ desc "steep check"
|
|
|
26
26
|
task :steep do
|
|
27
27
|
sh "bundle exec steep check"
|
|
28
28
|
end
|
|
29
|
+
task :steep => :rbs_inline
|
|
29
30
|
|
|
30
31
|
desc "Run rbs-inline"
|
|
31
32
|
task :rbs_inline do
|
|
32
33
|
sh "bundle exec rbs-inline --output lib/"
|
|
33
34
|
end
|
|
34
35
|
|
|
35
|
-
task default: %i[spec
|
|
36
|
+
task default: %i[spec steep]
|
data/Steepfile
CHANGED
|
@@ -6,19 +6,25 @@ target :lib do
|
|
|
6
6
|
repo_path '.gem_rbs_collection/'
|
|
7
7
|
signature "sig"
|
|
8
8
|
|
|
9
|
-
check "lib/lrama/grammar"
|
|
10
|
-
|
|
11
9
|
check "lib/lrama/counterexamples"
|
|
10
|
+
check "lib/lrama/grammar"
|
|
12
11
|
check "lib/lrama/lexer"
|
|
13
|
-
check "lib/lrama/
|
|
12
|
+
check "lib/lrama/reporter"
|
|
14
13
|
check "lib/lrama/state"
|
|
15
14
|
check "lib/lrama/states"
|
|
15
|
+
check "lib/lrama/tracer"
|
|
16
|
+
check "lib/lrama/warnings"
|
|
16
17
|
check "lib/lrama/bitmap.rb"
|
|
17
18
|
check "lib/lrama/counterexamples.rb"
|
|
18
19
|
check "lib/lrama/digraph.rb"
|
|
20
|
+
check "lib/lrama/erb.rb"
|
|
19
21
|
check "lib/lrama/grammar.rb"
|
|
22
|
+
check "lib/lrama/lexer.rb"
|
|
20
23
|
check "lib/lrama/logger.rb"
|
|
24
|
+
check "lib/lrama/option_parser.rb"
|
|
21
25
|
check "lib/lrama/options.rb"
|
|
22
|
-
check "lib/lrama/
|
|
23
|
-
check "lib/lrama/
|
|
26
|
+
check "lib/lrama/reporter.rb"
|
|
27
|
+
check "lib/lrama/tracer.rb"
|
|
28
|
+
check "lib/lrama/version.rb"
|
|
29
|
+
check "lib/lrama/warnings.rb"
|
|
24
30
|
end
|
data/doc/Index.md
CHANGED
|
@@ -49,7 +49,7 @@ Enter the formula:
|
|
|
49
49
|
|
|
50
50
|
## Supported Ruby version
|
|
51
51
|
|
|
52
|
-
Lrama is executed with BASERUBY when building ruby from source code. Therefore Lrama needs to support BASERUBY, currently
|
|
52
|
+
Lrama is executed with BASERUBY when building ruby from source code. Therefore Lrama needs to support BASERUBY, currently 3.1, or later version.
|
|
53
53
|
|
|
54
54
|
This also requires Lrama to be able to run with only default gems because BASERUBY runs with `--disable=gems` option.
|
|
55
55
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Profiling Lrama
|
|
2
|
+
|
|
3
|
+
To help improve Lrama's processing speed and reduce its memory usage, Lrama supports two profiling options:
|
|
4
|
+
|
|
5
|
+
* Call-stack profiling using the stackprof gem
|
|
6
|
+
* Memory profiling using the memory_profiler gem
|
|
7
|
+
|
|
8
|
+
## Call-stack Profiling Lrama
|
|
9
|
+
|
|
10
|
+
### 1. Create parse.tmp.y in ruby/ruby
|
|
11
|
+
|
|
12
|
+
```shell
|
|
13
|
+
$ ruby tool/id2token.rb parse.y > parse.tmp.y
|
|
14
|
+
$ cp parse.tmp.y dir/lrama/tmp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Run Lrama
|
|
18
|
+
|
|
19
|
+
```shell
|
|
20
|
+
$ exe/lrama -o parse.tmp.c --header=parse.tmp.h --profile=call-stack tmp/parse.tmp.y
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 3. Generate Flamegraph
|
|
24
|
+
|
|
25
|
+
```shell
|
|
26
|
+
$ stackprof --d3-flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph.html
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Memory Profiling Lrama
|
|
30
|
+
|
|
31
|
+
### 1. Create parse.tmp.y in ruby/ruby
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
$ ruby tool/id2token.rb parse.y > parse.tmp.y
|
|
35
|
+
$ cp parse.tmp.y dir/lrama/tmp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Run Lrama
|
|
39
|
+
|
|
40
|
+
```shell
|
|
41
|
+
$ exe/lrama -o parse.tmp.c --header=parse.tmp.h --profile=memory tmp/parse.tmp.y
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then "tmp/memory_profiler.txt" is generated.
|
data/exe/lrama
CHANGED
data/lib/lrama/bitmap.rb
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
module Lrama
|
|
5
5
|
module Bitmap
|
|
6
|
-
# @rbs
|
|
6
|
+
# @rbs!
|
|
7
|
+
# type bitmap = Integer
|
|
8
|
+
|
|
9
|
+
# @rbs (Array[Integer] ary) -> bitmap
|
|
7
10
|
def self.from_array(ary)
|
|
8
11
|
bit = 0
|
|
9
12
|
|
|
@@ -14,21 +17,31 @@ module Lrama
|
|
|
14
17
|
bit
|
|
15
18
|
end
|
|
16
19
|
|
|
17
|
-
# @rbs (Integer int) ->
|
|
20
|
+
# @rbs (Integer int) -> bitmap
|
|
21
|
+
def self.from_integer(int)
|
|
22
|
+
1 << int
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @rbs (bitmap int) -> Array[Integer]
|
|
18
26
|
def self.to_array(int)
|
|
19
27
|
a = [] #: Array[Integer]
|
|
20
28
|
i = 0
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
len = int.bit_length
|
|
31
|
+
while i < len do
|
|
32
|
+
if int[i] == 1
|
|
24
33
|
a << i
|
|
25
34
|
end
|
|
26
35
|
|
|
27
36
|
i += 1
|
|
28
|
-
int >>= 1
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
a
|
|
32
40
|
end
|
|
41
|
+
|
|
42
|
+
# @rbs (bitmap int, Integer size) -> Array[bool]
|
|
43
|
+
def self.to_bool_array(int, size)
|
|
44
|
+
Array.new(size) { |i| int[i] == 1 }
|
|
45
|
+
end
|
|
33
46
|
end
|
|
34
47
|
end
|
data/lib/lrama/command.rb
CHANGED
|
@@ -5,64 +5,116 @@ module Lrama
|
|
|
5
5
|
LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__)))
|
|
6
6
|
STDLIB_FILE_PATH = File.join(LRAMA_LIB, 'grammar', 'stdlib.y')
|
|
7
7
|
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Report::Duration.enable if options.trace_opts[:time]
|
|
8
|
+
def initialize(argv)
|
|
9
|
+
@logger = Lrama::Logger.new
|
|
10
|
+
@options = OptionParser.parse(argv)
|
|
11
|
+
@tracer = Tracer.new(STDERR, **@options.trace_opts)
|
|
12
|
+
@reporter = Reporter.new(**@options.report_opts)
|
|
13
|
+
@warnings = Warnings.new(@logger, @options.warnings)
|
|
14
|
+
rescue => e
|
|
15
|
+
abort format_error_message(e.message)
|
|
16
|
+
end
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
unless grammar.no_stdlib
|
|
24
|
-
stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
|
|
25
|
-
grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
|
|
18
|
+
def run
|
|
19
|
+
Lrama::Reporter::Profile::CallStack.report(@options.profile_opts[:call_stack]) do
|
|
20
|
+
Lrama::Reporter::Profile::Memory.report(@options.profile_opts[:memory]) do
|
|
21
|
+
execute_command_workflow
|
|
26
22
|
end
|
|
27
|
-
grammar.prepare
|
|
28
|
-
grammar.validate!
|
|
29
|
-
rescue => e
|
|
30
|
-
raise e if options.debug
|
|
31
|
-
message = e.message
|
|
32
|
-
message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
|
|
33
|
-
abort message
|
|
34
23
|
end
|
|
35
|
-
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def execute_command_workflow
|
|
29
|
+
@tracer.enable_duration
|
|
30
|
+
text = read_input
|
|
31
|
+
grammar = build_grammar(text)
|
|
32
|
+
states, context = compute_status(grammar)
|
|
33
|
+
render_reports(states) if @options.report_file
|
|
34
|
+
@tracer.trace(grammar)
|
|
35
|
+
render_diagram(grammar)
|
|
36
|
+
render_output(context, grammar)
|
|
37
|
+
states.validate!(@logger)
|
|
38
|
+
@warnings.warn(grammar, states)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def read_input
|
|
42
|
+
text = @options.y.read
|
|
43
|
+
@options.y.close unless @options.y == STDIN
|
|
44
|
+
text
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def build_grammar(text)
|
|
48
|
+
grammar =
|
|
49
|
+
Lrama::Parser.new(text, @options.grammar_file, @options.debug, @options.locations, @options.define).parse
|
|
50
|
+
merge_stdlib(grammar)
|
|
51
|
+
prepare_grammar(grammar)
|
|
52
|
+
grammar
|
|
53
|
+
rescue => e
|
|
54
|
+
raise e if @options.debug
|
|
55
|
+
abort format_error_message(e.message)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def format_error_message(message)
|
|
59
|
+
return message unless Exception.to_tty?
|
|
60
|
+
|
|
61
|
+
message.gsub(/.+/, "\e[1m\\&\e[m")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def merge_stdlib(grammar)
|
|
65
|
+
return if grammar.no_stdlib
|
|
66
|
+
|
|
67
|
+
stdlib_text = File.read(STDLIB_FILE_PATH)
|
|
68
|
+
stdlib_grammar = Lrama::Parser.new(
|
|
69
|
+
stdlib_text,
|
|
70
|
+
STDLIB_FILE_PATH,
|
|
71
|
+
@options.debug,
|
|
72
|
+
@options.locations,
|
|
73
|
+
@options.define,
|
|
74
|
+
).parse
|
|
75
|
+
|
|
76
|
+
grammar.prepend_parameterized_rules(stdlib_grammar.parameterized_rules)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def prepare_grammar(grammar)
|
|
80
|
+
grammar.prepare
|
|
81
|
+
grammar.validate!
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def compute_status(grammar)
|
|
85
|
+
states = Lrama::States.new(grammar, @tracer)
|
|
36
86
|
states.compute
|
|
37
87
|
states.compute_ielr if grammar.ielr_defined?
|
|
38
|
-
|
|
88
|
+
[states, Lrama::Context.new(states)]
|
|
89
|
+
end
|
|
39
90
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
reporter.report(f, **options.report_opts)
|
|
44
|
-
end
|
|
91
|
+
def render_reports(states)
|
|
92
|
+
File.open(@options.report_file, "w+") do |f|
|
|
93
|
+
@reporter.report(f, states)
|
|
45
94
|
end
|
|
95
|
+
end
|
|
46
96
|
|
|
47
|
-
|
|
48
|
-
|
|
97
|
+
def render_diagram(grammar)
|
|
98
|
+
return unless @options.diagram
|
|
49
99
|
|
|
50
|
-
File.open(options.
|
|
100
|
+
File.open(@options.diagram_file, "w+") do |f|
|
|
101
|
+
Lrama::Diagram.render(out: f, grammar: grammar)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def render_output(context, grammar)
|
|
106
|
+
File.open(@options.outfile, "w+") do |f|
|
|
51
107
|
Lrama::Output.new(
|
|
52
108
|
out: f,
|
|
53
|
-
output_file_path: options.outfile,
|
|
54
|
-
template_name: options.skeleton,
|
|
55
|
-
grammar_file_path: options.grammar_file,
|
|
56
|
-
header_file_path: options.header_file,
|
|
109
|
+
output_file_path: @options.outfile,
|
|
110
|
+
template_name: @options.skeleton,
|
|
111
|
+
grammar_file_path: @options.grammar_file,
|
|
112
|
+
header_file_path: @options.header_file,
|
|
57
113
|
context: context,
|
|
58
114
|
grammar: grammar,
|
|
59
|
-
error_recovery: options.error_recovery,
|
|
115
|
+
error_recovery: @options.error_recovery,
|
|
60
116
|
).render
|
|
61
117
|
end
|
|
62
|
-
|
|
63
|
-
logger = Lrama::Logger.new
|
|
64
|
-
exit false unless Lrama::GrammarValidator.new(grammar, states, logger).valid?
|
|
65
|
-
Lrama::Diagnostics.new(grammar, states, logger).run(options.diagnostic)
|
|
66
118
|
end
|
|
67
119
|
end
|
|
68
120
|
end
|
data/lib/lrama/context.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "tracer/duration"
|
|
4
4
|
|
|
5
5
|
module Lrama
|
|
6
6
|
# This is passed to a template
|
|
7
7
|
class Context
|
|
8
|
-
include
|
|
8
|
+
include Tracer::Duration
|
|
9
9
|
|
|
10
10
|
ErrorActionNumber = -Float::INFINITY
|
|
11
11
|
BaseMin = -Float::INFINITY
|
|
@@ -231,8 +231,8 @@ module Lrama
|
|
|
231
231
|
end
|
|
232
232
|
|
|
233
233
|
# Shift is selected when S/R conflict exists.
|
|
234
|
-
state.selected_term_transitions.each do |shift
|
|
235
|
-
actions[shift.next_sym.number] =
|
|
234
|
+
state.selected_term_transitions.each do |shift|
|
|
235
|
+
actions[shift.next_sym.number] = shift.to_state.id
|
|
236
236
|
end
|
|
237
237
|
|
|
238
238
|
state.resolved_conflicts.select do |conflict|
|
|
@@ -292,18 +292,18 @@ module Lrama
|
|
|
292
292
|
# of a default nterm transition destination.
|
|
293
293
|
@yydefgoto = Array.new(@states.nterms.count, 0)
|
|
294
294
|
# Mapping from nterm to next_states
|
|
295
|
-
|
|
295
|
+
nterm_to_to_states = {}
|
|
296
296
|
|
|
297
297
|
@states.states.each do |state|
|
|
298
|
-
state.nterm_transitions.each do |
|
|
299
|
-
key =
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
state.nterm_transitions.each do |goto|
|
|
299
|
+
key = goto.next_sym
|
|
300
|
+
nterm_to_to_states[key] ||= []
|
|
301
|
+
nterm_to_to_states[key] << [state, goto.to_state] # [from_state, to_state]
|
|
302
302
|
end
|
|
303
303
|
end
|
|
304
304
|
|
|
305
305
|
@states.nterms.each do |nterm|
|
|
306
|
-
if (states =
|
|
306
|
+
if (states = nterm_to_to_states[nterm])
|
|
307
307
|
default_state = states.map(&:last).group_by {|s| s }.max_by {|_, v| v.count }.first
|
|
308
308
|
default_goto = default_state.id
|
|
309
309
|
not_default_gotos = []
|
|
@@ -417,27 +417,25 @@ module Lrama
|
|
|
417
417
|
|
|
418
418
|
res = lowzero - froms_and_tos.first[0]
|
|
419
419
|
|
|
420
|
+
# Find the smallest `res` such that `@table[res + from]` is empty for all `from` in `froms_and_tos`
|
|
420
421
|
while true do
|
|
421
|
-
|
|
422
|
+
advanced = false
|
|
422
423
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if @table[loc]
|
|
427
|
-
# If the cell of table is set, can not use the cell.
|
|
428
|
-
ok = false
|
|
429
|
-
break
|
|
430
|
-
end
|
|
424
|
+
while used_res[res]
|
|
425
|
+
res += 1
|
|
426
|
+
advanced = true
|
|
431
427
|
end
|
|
432
428
|
|
|
433
|
-
|
|
434
|
-
|
|
429
|
+
froms_and_tos.each do |from, to|
|
|
430
|
+
while @table[res + from]
|
|
431
|
+
res += 1
|
|
432
|
+
advanced = true
|
|
433
|
+
end
|
|
435
434
|
end
|
|
436
435
|
|
|
437
|
-
|
|
436
|
+
unless advanced
|
|
437
|
+
# no advance means that the current `res` satisfies the condition
|
|
438
438
|
break
|
|
439
|
-
else
|
|
440
|
-
res += 1
|
|
441
439
|
end
|
|
442
440
|
end
|
|
443
441
|
|
|
@@ -1,34 +1,44 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Lrama
|
|
4
5
|
class Counterexamples
|
|
5
6
|
class Derivation
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
# @rbs!
|
|
8
|
+
# @item: State::Item
|
|
9
|
+
# @left: Derivation?
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
attr_reader :item #: State::Item
|
|
12
|
+
attr_reader :left #: Derivation?
|
|
13
|
+
attr_accessor :right #: Derivation?
|
|
14
|
+
|
|
15
|
+
# @rbs (State::Item item, Derivation? left) -> void
|
|
16
|
+
def initialize(item, left)
|
|
10
17
|
@item = item
|
|
11
18
|
@left = left
|
|
12
|
-
@right = right
|
|
13
19
|
end
|
|
14
20
|
|
|
21
|
+
# @rbs () -> ::String
|
|
15
22
|
def to_s
|
|
16
23
|
"#<Derivation(#{item.display_name})>"
|
|
17
24
|
end
|
|
18
25
|
alias :inspect :to_s
|
|
19
26
|
|
|
27
|
+
# @rbs () -> Array[String]
|
|
20
28
|
def render_strings_for_report
|
|
21
29
|
result = [] #: Array[String]
|
|
22
30
|
_render_for_report(self, 0, result, 0)
|
|
23
31
|
result.map(&:rstrip)
|
|
24
32
|
end
|
|
25
33
|
|
|
34
|
+
# @rbs () -> String
|
|
26
35
|
def render_for_report
|
|
27
36
|
render_strings_for_report.join("\n")
|
|
28
37
|
end
|
|
29
38
|
|
|
30
39
|
private
|
|
31
40
|
|
|
41
|
+
# @rbs (Derivation derivation, Integer offset, Array[String] strings, Integer index) -> Integer
|
|
32
42
|
def _render_for_report(derivation, offset, strings, index)
|
|
33
43
|
item = derivation.item
|
|
34
44
|
if strings[index]
|
|
@@ -1,12 +1,31 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Lrama
|
|
4
5
|
class Counterexamples
|
|
5
6
|
class Example
|
|
6
|
-
|
|
7
|
+
# TODO: rbs-inline 0.11.0 doesn't support instance variables.
|
|
8
|
+
# Move these type declarations above instance variable definitions, once it's supported.
|
|
9
|
+
# see: https://github.com/soutaro/rbs-inline/pull/149
|
|
10
|
+
#
|
|
11
|
+
# @rbs!
|
|
12
|
+
# @path1: ::Array[StateItem]
|
|
13
|
+
# @path2: ::Array[StateItem]
|
|
14
|
+
# @conflict: State::conflict
|
|
15
|
+
# @conflict_symbol: Grammar::Symbol
|
|
16
|
+
# @counterexamples: Counterexamples
|
|
17
|
+
# @derivations1: Derivation
|
|
18
|
+
# @derivations2: Derivation
|
|
19
|
+
|
|
20
|
+
attr_reader :path1 #: ::Array[StateItem]
|
|
21
|
+
attr_reader :path2 #: ::Array[StateItem]
|
|
22
|
+
attr_reader :conflict #: State::conflict
|
|
23
|
+
attr_reader :conflict_symbol #: Grammar::Symbol
|
|
7
24
|
|
|
8
25
|
# path1 is shift conflict when S/R conflict
|
|
9
26
|
# path2 is always reduce conflict
|
|
27
|
+
#
|
|
28
|
+
# @rbs (Array[StateItem]? path1, Array[StateItem]? path2, State::conflict conflict, Grammar::Symbol conflict_symbol, Counterexamples counterexamples) -> void
|
|
10
29
|
def initialize(path1, path2, conflict, conflict_symbol, counterexamples)
|
|
11
30
|
@path1 = path1
|
|
12
31
|
@path2 = path2
|
|
@@ -15,69 +34,75 @@ module Lrama
|
|
|
15
34
|
@counterexamples = counterexamples
|
|
16
35
|
end
|
|
17
36
|
|
|
37
|
+
# @rbs () -> (:shift_reduce | :reduce_reduce)
|
|
18
38
|
def type
|
|
19
39
|
@conflict.type
|
|
20
40
|
end
|
|
21
41
|
|
|
42
|
+
# @rbs () -> State::Item
|
|
22
43
|
def path1_item
|
|
23
|
-
@path1.last.
|
|
44
|
+
@path1.last.item
|
|
24
45
|
end
|
|
25
46
|
|
|
47
|
+
# @rbs () -> State::Item
|
|
26
48
|
def path2_item
|
|
27
|
-
@path2.last.
|
|
49
|
+
@path2.last.item
|
|
28
50
|
end
|
|
29
51
|
|
|
52
|
+
# @rbs () -> Derivation
|
|
30
53
|
def derivations1
|
|
31
54
|
@derivations1 ||= _derivations(path1)
|
|
32
55
|
end
|
|
33
56
|
|
|
57
|
+
# @rbs () -> Derivation
|
|
34
58
|
def derivations2
|
|
35
59
|
@derivations2 ||= _derivations(path2)
|
|
36
60
|
end
|
|
37
61
|
|
|
38
62
|
private
|
|
39
63
|
|
|
40
|
-
|
|
64
|
+
# @rbs (Array[StateItem] state_items) -> Derivation
|
|
65
|
+
def _derivations(state_items)
|
|
41
66
|
derivation = nil #: Derivation
|
|
42
67
|
current = :production
|
|
43
|
-
|
|
44
|
-
lookahead_sym =
|
|
68
|
+
last_state_item = state_items.last #: StateItem
|
|
69
|
+
lookahead_sym = last_state_item.item.end_of_rule? ? @conflict_symbol : nil
|
|
45
70
|
|
|
46
|
-
|
|
47
|
-
item =
|
|
71
|
+
state_items.reverse_each do |si|
|
|
72
|
+
item = si.item
|
|
48
73
|
|
|
49
74
|
case current
|
|
50
75
|
when :production
|
|
51
|
-
case
|
|
52
|
-
when
|
|
76
|
+
case si.type
|
|
77
|
+
when :start
|
|
53
78
|
derivation = Derivation.new(item, derivation)
|
|
54
79
|
current = :start
|
|
55
|
-
when
|
|
80
|
+
when :transition
|
|
56
81
|
derivation = Derivation.new(item, derivation)
|
|
57
82
|
current = :transition
|
|
58
|
-
when
|
|
83
|
+
when :production
|
|
59
84
|
derivation = Derivation.new(item, derivation)
|
|
60
85
|
current = :production
|
|
61
86
|
else
|
|
62
|
-
raise "Unexpected. #{
|
|
87
|
+
raise "Unexpected. #{si}"
|
|
63
88
|
end
|
|
64
89
|
|
|
65
90
|
if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym)
|
|
66
|
-
|
|
67
|
-
derivation2 = find_derivation_for_symbol(
|
|
91
|
+
si2 = @counterexamples.transitions[[si, item.next_sym]]
|
|
92
|
+
derivation2 = find_derivation_for_symbol(si2, lookahead_sym)
|
|
68
93
|
derivation.right = derivation2 # steep:ignore
|
|
69
94
|
lookahead_sym = nil
|
|
70
95
|
end
|
|
71
96
|
|
|
72
97
|
when :transition
|
|
73
|
-
case
|
|
74
|
-
when
|
|
98
|
+
case si.type
|
|
99
|
+
when :start
|
|
75
100
|
derivation = Derivation.new(item, derivation)
|
|
76
101
|
current = :start
|
|
77
|
-
when
|
|
102
|
+
when :transition
|
|
78
103
|
# ignore
|
|
79
104
|
current = :transition
|
|
80
|
-
when
|
|
105
|
+
when :production
|
|
81
106
|
# ignore
|
|
82
107
|
current = :production
|
|
83
108
|
end
|
|
@@ -91,6 +116,7 @@ module Lrama
|
|
|
91
116
|
derivation
|
|
92
117
|
end
|
|
93
118
|
|
|
119
|
+
# @rbs (StateItem state_item, Grammar::Symbol sym) -> Derivation?
|
|
94
120
|
def find_derivation_for_symbol(state_item, sym)
|
|
95
121
|
queue = [] #: Array[Array[StateItem]]
|
|
96
122
|
queue << [state_item]
|
|
@@ -110,9 +136,8 @@ module Lrama
|
|
|
110
136
|
end
|
|
111
137
|
|
|
112
138
|
if next_sym.nterm? && next_sym.first_set.include?(sym)
|
|
113
|
-
@counterexamples.productions[si].each do |
|
|
114
|
-
next if
|
|
115
|
-
next_si = StateItem.new(si.state, next_item)
|
|
139
|
+
@counterexamples.productions[si].each do |next_si|
|
|
140
|
+
next if next_si.item.empty_rule?
|
|
116
141
|
next if sis.include?(next_si)
|
|
117
142
|
queue << (sis + [next_si])
|
|
118
143
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Lrama
|
|
5
|
+
class Counterexamples
|
|
6
|
+
# @rbs generic E < Object -- Type of an element
|
|
7
|
+
class Node
|
|
8
|
+
attr_reader :elem #: E
|
|
9
|
+
attr_reader :next_node #: Node[E]?
|
|
10
|
+
|
|
11
|
+
# @rbs [E < Object] (Node[E] node) -> Array[E]
|
|
12
|
+
def self.to_a(node)
|
|
13
|
+
a = [] # steep:ignore UnannotatedEmptyCollection
|
|
14
|
+
|
|
15
|
+
while (node)
|
|
16
|
+
a << node.elem
|
|
17
|
+
node = node.next_node
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
a
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @rbs (E elem, Node[E]? next_node) -> void
|
|
24
|
+
def initialize(elem, next_node)
|
|
25
|
+
@elem = elem
|
|
26
|
+
@next_node = next_node
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|