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.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/codespell.yaml +1 -1
  4. data/.github/workflows/gh-pages.yml +5 -6
  5. data/.github/workflows/test.yaml +25 -14
  6. data/Gemfile +4 -3
  7. data/NEWS.md +370 -35
  8. data/README.md +7 -88
  9. data/Rakefile +3 -2
  10. data/Steepfile +11 -5
  11. data/doc/Index.md +1 -1
  12. data/doc/development/compressed_state_table/parser.rb +2 -0
  13. data/doc/development/profiling.md +44 -0
  14. data/exe/lrama +1 -1
  15. data/lib/lrama/bitmap.rb +18 -5
  16. data/lib/lrama/command.rb +95 -43
  17. data/lib/lrama/context.rb +22 -24
  18. data/lib/lrama/counterexamples/derivation.rb +14 -4
  19. data/lib/lrama/counterexamples/example.rb +47 -22
  20. data/lib/lrama/counterexamples/node.rb +30 -0
  21. data/lib/lrama/counterexamples/path.rb +12 -14
  22. data/lib/lrama/counterexamples/state_item.rb +24 -1
  23. data/lib/lrama/counterexamples/triple.rb +27 -9
  24. data/lib/lrama/counterexamples.rb +216 -88
  25. data/lib/lrama/diagram.rb +77 -0
  26. data/lib/lrama/digraph.rb +28 -7
  27. data/lib/lrama/erb.rb +29 -0
  28. data/lib/lrama/grammar/auxiliary.rb +6 -1
  29. data/lib/lrama/grammar/binding.rb +37 -25
  30. data/lib/lrama/grammar/code/destructor_code.rb +11 -0
  31. data/lib/lrama/grammar/code/initial_action_code.rb +3 -0
  32. data/lib/lrama/grammar/code/no_reference_code.rb +3 -0
  33. data/lib/lrama/grammar/code/printer_code.rb +11 -0
  34. data/lib/lrama/grammar/code/rule_action.rb +17 -0
  35. data/lib/lrama/grammar/code.rb +16 -1
  36. data/lib/lrama/grammar/counter.rb +10 -0
  37. data/lib/lrama/grammar/destructor.rb +14 -1
  38. data/lib/lrama/grammar/error_token.rb +14 -1
  39. data/lib/lrama/grammar/inline/resolver.rb +80 -0
  40. data/lib/lrama/grammar/inline.rb +3 -0
  41. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/resolver.rb +19 -8
  42. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/rhs.rb +7 -2
  43. data/lib/lrama/grammar/parameterized/rule.rb +36 -0
  44. data/lib/lrama/grammar/parameterized.rb +5 -0
  45. data/lib/lrama/grammar/percent_code.rb +12 -1
  46. data/lib/lrama/grammar/precedence.rb +43 -1
  47. data/lib/lrama/grammar/printer.rb +9 -0
  48. data/lib/lrama/grammar/reference.rb +13 -0
  49. data/lib/lrama/grammar/rule.rb +61 -1
  50. data/lib/lrama/grammar/rule_builder.rb +84 -69
  51. data/lib/lrama/grammar/stdlib.y +68 -48
  52. data/lib/lrama/grammar/symbol.rb +63 -19
  53. data/lib/lrama/grammar/symbols/resolver.rb +64 -3
  54. data/lib/lrama/grammar/type.rb +13 -1
  55. data/lib/lrama/grammar/union.rb +12 -1
  56. data/lib/lrama/grammar.rb +231 -35
  57. data/lib/lrama/lexer/location.rb +25 -8
  58. data/lib/lrama/lexer/token/base.rb +73 -0
  59. data/lib/lrama/lexer/token/char.rb +15 -2
  60. data/lib/lrama/lexer/token/empty.rb +14 -0
  61. data/lib/lrama/lexer/token/ident.rb +2 -2
  62. data/lib/lrama/lexer/token/instantiate_rule.rb +4 -4
  63. data/lib/lrama/lexer/token/int.rb +14 -0
  64. data/lib/lrama/lexer/token/str.rb +11 -0
  65. data/lib/lrama/lexer/token/tag.rb +2 -2
  66. data/lib/lrama/lexer/token/token.rb +11 -0
  67. data/lib/lrama/lexer/token/user_code.rb +63 -37
  68. data/lib/lrama/lexer/token.rb +6 -56
  69. data/lib/lrama/lexer.rb +51 -23
  70. data/lib/lrama/logger.rb +12 -2
  71. data/lib/lrama/option_parser.rb +63 -9
  72. data/lib/lrama/options.rb +25 -7
  73. data/lib/lrama/output.rb +4 -11
  74. data/lib/lrama/parser.rb +854 -723
  75. data/lib/lrama/reporter/conflicts.rb +44 -0
  76. data/lib/lrama/reporter/grammar.rb +39 -0
  77. data/lib/lrama/reporter/precedences.rb +54 -0
  78. data/lib/lrama/reporter/profile/call_stack.rb +45 -0
  79. data/lib/lrama/reporter/profile/memory.rb +44 -0
  80. data/lib/lrama/reporter/profile.rb +4 -0
  81. data/lib/lrama/reporter/rules.rb +43 -0
  82. data/lib/lrama/reporter/states.rb +387 -0
  83. data/lib/lrama/reporter/terms.rb +44 -0
  84. data/lib/lrama/reporter.rb +39 -0
  85. data/lib/lrama/state/action/goto.rb +33 -0
  86. data/lib/lrama/state/action/reduce.rb +71 -0
  87. data/lib/lrama/state/action/shift.rb +39 -0
  88. data/lib/lrama/state/action.rb +5 -0
  89. data/lib/lrama/state/inadequacy_annotation.rb +140 -0
  90. data/lib/lrama/{states → state}/item.rb +33 -4
  91. data/lib/lrama/state/reduce_reduce_conflict.rb +14 -1
  92. data/lib/lrama/state/resolved_conflict.rb +38 -4
  93. data/lib/lrama/state/shift_reduce_conflict.rb +14 -1
  94. data/lib/lrama/state.rb +301 -200
  95. data/lib/lrama/states.rb +447 -175
  96. data/lib/lrama/tracer/actions.rb +22 -0
  97. data/lib/lrama/tracer/closure.rb +30 -0
  98. data/lib/lrama/tracer/duration.rb +38 -0
  99. data/lib/lrama/tracer/only_explicit_rules.rb +24 -0
  100. data/lib/lrama/tracer/rules.rb +23 -0
  101. data/lib/lrama/tracer/state.rb +33 -0
  102. data/lib/lrama/tracer.rb +51 -0
  103. data/lib/lrama/version.rb +2 -1
  104. data/lib/lrama/warnings/conflicts.rb +27 -0
  105. data/lib/lrama/warnings/implicit_empty.rb +29 -0
  106. data/lib/lrama/warnings/name_conflicts.rb +63 -0
  107. data/lib/lrama/warnings/redefined_rules.rb +23 -0
  108. data/lib/lrama/warnings/required.rb +23 -0
  109. data/lib/lrama/warnings/useless_precedence.rb +25 -0
  110. data/lib/lrama/warnings.rb +33 -0
  111. data/lib/lrama.rb +5 -5
  112. data/parser.y +495 -404
  113. data/rbs_collection.lock.yaml +27 -3
  114. data/rbs_collection.yaml +2 -0
  115. data/sig/generated/lrama/bitmap.rbs +12 -4
  116. data/sig/generated/lrama/counterexamples/derivation.rbs +36 -0
  117. data/sig/generated/lrama/counterexamples/example.rbs +58 -0
  118. data/sig/generated/lrama/counterexamples/node.rbs +18 -0
  119. data/sig/generated/lrama/counterexamples/path.rbs +23 -0
  120. data/sig/generated/lrama/counterexamples/state_item.rbs +19 -0
  121. data/sig/generated/lrama/counterexamples/triple.rbs +32 -0
  122. data/sig/generated/lrama/counterexamples.rbs +98 -0
  123. data/sig/generated/lrama/diagram.rbs +34 -0
  124. data/sig/generated/lrama/digraph.rbs +26 -6
  125. data/sig/generated/lrama/erb.rbs +14 -0
  126. data/sig/generated/lrama/grammar/auxiliary.rbs +16 -0
  127. data/sig/generated/lrama/grammar/binding.rbs +18 -12
  128. data/sig/generated/lrama/grammar/code/destructor_code.rbs +26 -0
  129. data/sig/{lrama → generated/lrama}/grammar/code/initial_action_code.rbs +6 -0
  130. data/sig/{lrama → generated/lrama}/grammar/code/no_reference_code.rbs +6 -0
  131. data/sig/generated/lrama/grammar/code/printer_code.rbs +26 -0
  132. data/sig/generated/lrama/grammar/code/rule_action.rbs +63 -0
  133. data/sig/generated/lrama/grammar/code.rbs +38 -0
  134. data/sig/{lrama → generated/lrama}/grammar/counter.rbs +4 -0
  135. data/sig/generated/lrama/grammar/destructor.rbs +19 -0
  136. data/sig/generated/lrama/grammar/error_token.rbs +19 -0
  137. data/sig/generated/lrama/grammar/inline/resolver.rbs +26 -0
  138. data/sig/generated/lrama/grammar/parameterized/resolver.rbs +42 -0
  139. data/sig/generated/lrama/grammar/parameterized/rhs.rbs +21 -0
  140. data/sig/generated/lrama/grammar/parameterized/rule.rbs +28 -0
  141. data/sig/{lrama → generated/lrama}/grammar/percent_code.rbs +8 -0
  142. data/sig/generated/lrama/grammar/precedence.rbs +45 -0
  143. data/sig/{lrama/grammar/error_token.rbs → generated/lrama/grammar/printer.rbs} +8 -3
  144. data/sig/generated/lrama/grammar/reference.rbs +31 -0
  145. data/sig/generated/lrama/grammar/rule.rbs +83 -0
  146. data/sig/generated/lrama/grammar/rule_builder.rbs +91 -0
  147. data/sig/generated/lrama/grammar/symbol.rbs +89 -0
  148. data/sig/generated/lrama/grammar/symbols/resolver.rbs +131 -0
  149. data/sig/generated/lrama/grammar/type.rbs +21 -0
  150. data/sig/generated/lrama/grammar/union.rbs +17 -0
  151. data/sig/generated/lrama/grammar.rbs +289 -0
  152. data/sig/generated/lrama/lexer/location.rbs +12 -3
  153. data/sig/generated/lrama/lexer/token/base.rbs +53 -0
  154. data/sig/generated/lrama/lexer/token/char.rbs +9 -2
  155. data/sig/generated/lrama/lexer/token/empty.rbs +11 -0
  156. data/sig/generated/lrama/lexer/token/ident.rbs +2 -2
  157. data/sig/generated/lrama/lexer/token/instantiate_rule.rbs +5 -5
  158. data/sig/generated/lrama/lexer/token/int.rbs +13 -0
  159. data/sig/generated/lrama/lexer/token/str.rbs +10 -0
  160. data/sig/generated/lrama/lexer/token/tag.rbs +2 -2
  161. data/sig/generated/lrama/lexer/token/token.rbs +10 -0
  162. data/sig/generated/lrama/lexer/token/user_code.rbs +2 -2
  163. data/sig/generated/lrama/lexer/token.rbs +1 -39
  164. data/sig/generated/lrama/lexer.rbs +54 -0
  165. data/sig/generated/lrama/logger.rbs +6 -0
  166. data/sig/generated/lrama/option_parser.rbs +52 -0
  167. data/sig/{lrama → generated/lrama}/options.rbs +27 -3
  168. data/sig/generated/lrama/reporter/conflicts.rbs +18 -0
  169. data/sig/generated/lrama/reporter/grammar.rbs +13 -0
  170. data/sig/generated/lrama/reporter/precedences.rbs +15 -0
  171. data/sig/generated/lrama/reporter/profile/call_stack.rbs +19 -0
  172. data/sig/generated/lrama/reporter/profile/memory.rbs +19 -0
  173. data/sig/generated/lrama/reporter/rules.rbs +13 -0
  174. data/sig/generated/lrama/reporter/states.rbs +69 -0
  175. data/sig/generated/lrama/reporter/terms.rbs +13 -0
  176. data/sig/generated/lrama/reporter.rbs +13 -0
  177. data/sig/generated/lrama/state/action/goto.rbs +28 -0
  178. data/sig/generated/lrama/state/action/reduce.rbs +49 -0
  179. data/sig/generated/lrama/state/action/shift.rbs +33 -0
  180. data/sig/generated/lrama/state/inadequacy_annotation.rbs +45 -0
  181. data/sig/generated/lrama/state/item.rbs +75 -0
  182. data/sig/generated/lrama/state/reduce_reduce_conflict.rbs +19 -0
  183. data/sig/generated/lrama/state/resolved_conflict.rbs +38 -0
  184. data/sig/generated/lrama/state/shift_reduce_conflict.rbs +19 -0
  185. data/sig/generated/lrama/state.rbs +231 -0
  186. data/sig/generated/lrama/states.rbs +215 -0
  187. data/sig/generated/lrama/tracer/actions.rbs +13 -0
  188. data/sig/generated/lrama/tracer/closure.rbs +13 -0
  189. data/sig/generated/lrama/tracer/duration.rbs +18 -0
  190. data/sig/generated/lrama/tracer/only_explicit_rules.rbs +13 -0
  191. data/sig/generated/lrama/tracer/rules.rbs +13 -0
  192. data/sig/generated/lrama/tracer/state.rbs +16 -0
  193. data/sig/generated/lrama/tracer.rbs +23 -0
  194. data/sig/generated/lrama/version.rbs +5 -0
  195. data/sig/generated/lrama/warnings/conflicts.rbs +13 -0
  196. data/sig/generated/lrama/warnings/implicit_empty.rbs +17 -0
  197. data/sig/generated/lrama/warnings/name_conflicts.rbs +31 -0
  198. data/sig/generated/lrama/warnings/redefined_rules.rbs +13 -0
  199. data/sig/generated/lrama/warnings/required.rbs +13 -0
  200. data/sig/generated/lrama/warnings/useless_precedence.rbs +13 -0
  201. data/sig/generated/lrama/warnings.rbs +11 -0
  202. data/sig/railroad_diagrams/railroad_diagrams.rbs +16 -0
  203. data/template/bison/_yacc.h +8 -0
  204. data/template/diagram/diagram.html +102 -0
  205. metadata +126 -66
  206. data/lib/lrama/counterexamples/production_path.rb +0 -19
  207. data/lib/lrama/counterexamples/start_path.rb +0 -23
  208. data/lib/lrama/counterexamples/transition_path.rb +0 -19
  209. data/lib/lrama/diagnostics.rb +0 -36
  210. data/lib/lrama/grammar/parameterizing_rule/rule.rb +0 -24
  211. data/lib/lrama/grammar/parameterizing_rule.rb +0 -5
  212. data/lib/lrama/grammar_validator.rb +0 -37
  213. data/lib/lrama/report/duration.rb +0 -27
  214. data/lib/lrama/report/profile.rb +0 -16
  215. data/lib/lrama/report.rb +0 -4
  216. data/lib/lrama/state/reduce.rb +0 -37
  217. data/lib/lrama/state/shift.rb +0 -15
  218. data/lib/lrama/states_reporter.rb +0 -362
  219. data/lib/lrama/trace_reporter.rb +0 -45
  220. data/sig/generated/lrama/trace_reporter.rbs +0 -25
  221. data/sig/lrama/counterexamples/derivation.rbs +0 -33
  222. data/sig/lrama/counterexamples/example.rbs +0 -45
  223. data/sig/lrama/counterexamples/path.rbs +0 -21
  224. data/sig/lrama/counterexamples/production_path.rbs +0 -11
  225. data/sig/lrama/counterexamples/start_path.rbs +0 -13
  226. data/sig/lrama/counterexamples/state_item.rbs +0 -10
  227. data/sig/lrama/counterexamples/transition_path.rbs +0 -11
  228. data/sig/lrama/counterexamples/triple.rbs +0 -20
  229. data/sig/lrama/counterexamples.rbs +0 -29
  230. data/sig/lrama/grammar/auxiliary.rbs +0 -10
  231. data/sig/lrama/grammar/code/destructor_code.rbs +0 -14
  232. data/sig/lrama/grammar/code/printer_code.rbs +0 -14
  233. data/sig/lrama/grammar/code/rule_action.rbs +0 -19
  234. data/sig/lrama/grammar/code.rbs +0 -24
  235. data/sig/lrama/grammar/destructor.rbs +0 -13
  236. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +0 -24
  237. data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +0 -14
  238. data/sig/lrama/grammar/parameterizing_rule/rule.rbs +0 -16
  239. data/sig/lrama/grammar/parameterizing_rule.rbs +0 -6
  240. data/sig/lrama/grammar/precedence.rbs +0 -13
  241. data/sig/lrama/grammar/printer.rbs +0 -13
  242. data/sig/lrama/grammar/reference.rbs +0 -22
  243. data/sig/lrama/grammar/rule.rbs +0 -45
  244. data/sig/lrama/grammar/rule_builder.rbs +0 -47
  245. data/sig/lrama/grammar/symbol.rbs +0 -38
  246. data/sig/lrama/grammar/symbols/resolver.rbs +0 -60
  247. data/sig/lrama/grammar/type.rbs +0 -11
  248. data/sig/lrama/grammar/union.rbs +0 -12
  249. data/sig/lrama/grammar.rbs +0 -108
  250. data/sig/lrama/report/duration.rbs +0 -11
  251. data/sig/lrama/report/profile.rbs +0 -7
  252. data/sig/lrama/state/reduce.rbs +0 -20
  253. data/sig/lrama/state/reduce_reduce_conflict.rbs +0 -13
  254. data/sig/lrama/state/resolved_conflict.rbs +0 -14
  255. data/sig/lrama/state/shift.rbs +0 -14
  256. data/sig/lrama/state/shift_reduce_conflict.rbs +0 -13
  257. data/sig/lrama/state.rbs +0 -79
  258. data/sig/lrama/states/item.rbs +0 -30
  259. data/sig/lrama/states.rbs +0 -101
  260. 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 rbs_inline steep]
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/report"
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/trace_reporter.rb"
23
- check "lib/lrama/warning.rb"
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 2.5, or later version.
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
 
@@ -1,3 +1,4 @@
1
+ # :nodoc: all
1
2
  class Parser
2
3
  YYNTOKENS = 9
3
4
  YYLAST = 13
@@ -253,6 +254,7 @@ class Parser
253
254
  end
254
255
  end
255
256
 
257
+ # :nodoc: all
256
258
  class Lexer
257
259
  def initialize(tokens)
258
260
  @tokens = tokens
@@ -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
@@ -4,4 +4,4 @@
4
4
  $LOAD_PATH << File.join(__dir__, "../lib")
5
5
  require "lrama"
6
6
 
7
- Lrama::Command.new.run(ARGV.dup)
7
+ Lrama::Command.new(ARGV.dup).run
data/lib/lrama/bitmap.rb CHANGED
@@ -3,7 +3,10 @@
3
3
 
4
4
  module Lrama
5
5
  module Bitmap
6
- # @rbs (Array[Integer] ary) -> Integer
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) -> Array[Integer]
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
- while int > 0 do
23
- if int & 1 == 1
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 run(argv)
9
- begin
10
- options = OptionParser.new.parse(argv)
11
- rescue => e
12
- message = e.message
13
- message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
14
- abort message
15
- end
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
- text = options.y.read
20
- options.y.close if options.y != STDIN
21
- begin
22
- grammar = Lrama::Parser.new(text, options.grammar_file, options.debug, options.define).parse
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
- states = Lrama::States.new(grammar, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
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
- context = Lrama::Context.new(states)
88
+ [states, Lrama::Context.new(states)]
89
+ end
39
90
 
40
- if options.report_file
41
- reporter = Lrama::StatesReporter.new(states)
42
- File.open(options.report_file, "w+") do |f|
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
- reporter = Lrama::TraceReporter.new(grammar)
48
- reporter.report(**options.trace_opts)
97
+ def render_diagram(grammar)
98
+ return unless @options.diagram
49
99
 
50
- File.open(options.outfile, "w+") do |f|
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 "report/duration"
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 Report::Duration
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, next_state|
235
- actions[shift.next_sym.number] = next_state.id
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
- nterm_to_next_states = {}
295
+ nterm_to_to_states = {}
296
296
 
297
297
  @states.states.each do |state|
298
- state.nterm_transitions.each do |shift, next_state|
299
- key = shift.next_sym
300
- nterm_to_next_states[key] ||= []
301
- nterm_to_next_states[key] << [state, next_state] # [from_state, to_state]
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 = nterm_to_next_states[nterm])
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
- ok = true
422
+ advanced = false
422
423
 
423
- froms_and_tos.each do |from, to|
424
- loc = res + from
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
- if ok && used_res[res]
434
- ok = false
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
- if ok
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
- attr_reader :item, :left, :right
7
- attr_writer :right
7
+ # @rbs!
8
+ # @item: State::Item
9
+ # @left: Derivation?
8
10
 
9
- def initialize(item, left, right = nil)
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
- attr_reader :path1, :path2, :conflict, :conflict_symbol
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.to.item
44
+ @path1.last.item
24
45
  end
25
46
 
47
+ # @rbs () -> State::Item
26
48
  def path2_item
27
- @path2.last.to.item
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
- def _derivations(paths)
64
+ # @rbs (Array[StateItem] state_items) -> Derivation
65
+ def _derivations(state_items)
41
66
  derivation = nil #: Derivation
42
67
  current = :production
43
- last_path = paths.last #: Path
44
- lookahead_sym = last_path.to.item.end_of_rule? ? @conflict_symbol : nil
68
+ last_state_item = state_items.last #: StateItem
69
+ lookahead_sym = last_state_item.item.end_of_rule? ? @conflict_symbol : nil
45
70
 
46
- paths.reverse_each do |path|
47
- item = path.to.item
71
+ state_items.reverse_each do |si|
72
+ item = si.item
48
73
 
49
74
  case current
50
75
  when :production
51
- case path
52
- when StartPath
76
+ case si.type
77
+ when :start
53
78
  derivation = Derivation.new(item, derivation)
54
79
  current = :start
55
- when TransitionPath
80
+ when :transition
56
81
  derivation = Derivation.new(item, derivation)
57
82
  current = :transition
58
- when ProductionPath
83
+ when :production
59
84
  derivation = Derivation.new(item, derivation)
60
85
  current = :production
61
86
  else
62
- raise "Unexpected. #{path}"
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
- state_item = @counterexamples.transitions[[path.to, item.next_sym]]
67
- derivation2 = find_derivation_for_symbol(state_item, lookahead_sym)
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 path
74
- when StartPath
98
+ case si.type
99
+ when :start
75
100
  derivation = Derivation.new(item, derivation)
76
101
  current = :start
77
- when TransitionPath
102
+ when :transition
78
103
  # ignore
79
104
  current = :transition
80
- when ProductionPath
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 |next_item|
114
- next if next_item.empty_rule?
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