lrama 0.5.1 → 0.5.3

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.
data/lib/lrama/parser.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "lrama/report"
1
+ require "lrama/report/duration"
2
2
  require "lrama/parser/token_scanner"
3
3
 
4
4
  module Lrama
@@ -59,6 +59,13 @@ module Lrama
59
59
  code = grammar.build_code(:printer, code)
60
60
  ident_or_tags = ts.consume_multi(T::Ident, T::Tag)
61
61
  grammar.add_printer(ident_or_tags: ident_or_tags, code: code, lineno: lineno)
62
+ when T::P_error_token
63
+ lineno = ts.current_token.line
64
+ ts.next
65
+ code = ts.consume!(T::User_code)
66
+ code = grammar.build_code(:printer, code)
67
+ ident_or_tags = ts.consume_multi(T::Ident, T::Tag)
68
+ grammar.add_error_token(ident_or_tags: ident_or_tags, code: code, lineno: lineno)
62
69
  when T::P_lex_param
63
70
  ts.next
64
71
  code = ts.consume!(T::User_code)
@@ -175,8 +182,11 @@ module Lrama
175
182
  # LHS
176
183
  lhs = ts.consume!(T::Ident_Colon) # class:
177
184
  lhs.type = T::Ident
185
+ if named_ref = ts.consume(T::Named_Ref)
186
+ lhs.alias = named_ref.s_value
187
+ end
178
188
 
179
- rhs = parse_grammar_rule_rhs(ts, grammar)
189
+ rhs = parse_grammar_rule_rhs(ts, grammar, lhs)
180
190
 
181
191
  grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : lhs.line)
182
192
 
@@ -186,7 +196,7 @@ module Lrama
186
196
  # |
187
197
  bar_lineno = ts.current_token.line
188
198
  ts.next
189
- rhs = parse_grammar_rule_rhs(ts, grammar)
199
+ rhs = parse_grammar_rule_rhs(ts, grammar, lhs)
190
200
  grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : bar_lineno)
191
201
  when T::Semicolon
192
202
  # ;
@@ -205,13 +215,13 @@ module Lrama
205
215
  end
206
216
  end
207
217
 
208
- def parse_grammar_rule_rhs(ts, grammar)
218
+ def parse_grammar_rule_rhs(ts, grammar, lhs)
209
219
  a = []
210
220
  prec_seen = false
211
221
  code_after_prec = false
212
222
 
213
223
  while true do
214
- # TODO: Srting can be here
224
+ # TODO: String can be here
215
225
  case ts.current_type
216
226
  when T::Ident
217
227
  # keyword_class
@@ -244,9 +254,13 @@ module Lrama
244
254
  end
245
255
 
246
256
  code = ts.current_token
257
+ code.numberize_references(lhs, a)
247
258
  grammar.build_references(code)
248
259
  a << code
249
260
  ts.next
261
+ when T::Named_Ref
262
+ ts.previous_token.alias = ts.current_token.s_value
263
+ ts.next
250
264
  when T::Bar
251
265
  # |
252
266
  break
@@ -0,0 +1,25 @@
1
+ module Lrama
2
+ class Report
3
+ module Duration
4
+ def self.enable
5
+ @_report_duration_enabled = true
6
+ end
7
+
8
+ def self.enabled?
9
+ !!@_report_duration_enabled
10
+ end
11
+
12
+ def report_duration(method_name)
13
+ time1 = Time.now.to_f
14
+ result = yield
15
+ time2 = Time.now.to_f
16
+
17
+ if Duration.enabled?
18
+ puts sprintf("%s %10.5f s", method_name, time2 - time1)
19
+ end
20
+
21
+ return result
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Lrama
2
+ class Report
3
+ module Profile
4
+ # 1. Wrap target method with Profile.report_profile like below:
5
+ #
6
+ # Lrama::Report::Profile.report_profile { method }
7
+ #
8
+ # 2. Run lrama command, for example
9
+ #
10
+ # $ ./exe/lrama --trace=time spec/fixtures/integration/ruby_3_2_0/parse.tmp.y
11
+ #
12
+ # 3. Generate html file
13
+ #
14
+ # $ stackprof --d3-flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph.html
15
+ #
16
+ def self.report_profile
17
+ require "stackprof"
18
+
19
+ StackProf.run(mode: :cpu, raw: true, out: 'tmp/stackprof-cpu-myapp.dump') do
20
+ yield
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/lrama/report.rb CHANGED
@@ -1,47 +1,2 @@
1
- module Lrama
2
- class Report
3
- module Profile
4
- # 1. Wrap target method with Profile.report_profile like below:
5
- #
6
- # Lrama::Report::Profile.report_profile { method }
7
- #
8
- # 2. Run lrama command, for example
9
- #
10
- # $ ./exe/lrama --trace=time spec/fixtures/integration/ruby_3_2_0/parse.tmp.y
11
- #
12
- # 3. Generate html file
13
- #
14
- # $ stackprof --d3-flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph.html
15
- #
16
- def self.report_profile
17
- require "stackprof"
18
-
19
- StackProf.run(mode: :cpu, raw: true, out: 'tmp/stackprof-cpu-myapp.dump') do
20
- yield
21
- end
22
- end
23
- end
24
-
25
- module Duration
26
- def self.enable
27
- @_report_duration_enabled = true
28
- end
29
-
30
- def self.enabled?
31
- !!@_report_duration_enabled
32
- end
33
-
34
- def report_duration(method_name)
35
- time1 = Time.now.to_f
36
- result = yield
37
- time2 = Time.now.to_f
38
-
39
- if Duration.enabled?
40
- puts sprintf("%s %10.5f s", method_name, time2 - time1)
41
- end
42
-
43
- return result
44
- end
45
- end
46
- end
47
- end
1
+ require 'lrama/report/duration'
2
+ require 'lrama/report/profile'
@@ -0,0 +1,29 @@
1
+ module Lrama
2
+ class State
3
+ # * symbol: A symbol under discussion
4
+ # * reduce: A reduce under discussion
5
+ # * which: For which a conflict is resolved. :shift, :reduce or :error (for nonassociative)
6
+ class ResolvedConflict < Struct.new(:symbol, :reduce, :which, :same_prec, keyword_init: true)
7
+ def report_message
8
+ s = symbol.display_name
9
+ r = reduce.rule.precedence_sym.display_name
10
+ case
11
+ when which == :shift && same_prec
12
+ msg = "resolved as #{which} (%right #{s})"
13
+ when which == :shift
14
+ msg = "resolved as #{which} (#{r} < #{s})"
15
+ when which == :reduce && same_prec
16
+ msg = "resolved as #{which} (%left #{s})"
17
+ when which == :reduce
18
+ msg = "resolved as #{which} (#{s} < #{r})"
19
+ when which == :error
20
+ msg = "resolved as an #{which} (%nonassoc #{s})"
21
+ else
22
+ raise "Unknown direction. #{self}"
23
+ end
24
+
25
+ "Conflict between rule #{reduce.rule.id} and token #{s} #{msg}."
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/lrama/state.rb CHANGED
@@ -1,34 +1,9 @@
1
1
  require "lrama/state/reduce"
2
2
  require "lrama/state/shift"
3
+ require "lrama/state/resolved_conflict"
3
4
 
4
5
  module Lrama
5
6
  class State
6
- # * symbol: A symbol under discussion
7
- # * reduce: A reduce under discussion
8
- # * which: For which a conflict is resolved. :shift, :reduce or :error (for nonassociative)
9
- ResolvedConflict = Struct.new(:symbol, :reduce, :which, :same_prec, keyword_init: true) do
10
- def report_message
11
- s = symbol.display_name
12
- r = reduce.rule.precedence_sym.display_name
13
- case
14
- when which == :shift && same_prec
15
- msg = "resolved as #{which} (%right #{s})"
16
- when which == :shift
17
- msg = "resolved as #{which} (#{r} < #{s})"
18
- when which == :reduce && same_prec
19
- msg = "resolved as #{which} (%left #{s})"
20
- when which == :reduce
21
- msg = "resolved as #{which} (#{s} < #{r})"
22
- when which == :error
23
- msg = "resolved as an #{which} (%nonassoc #{s})"
24
- else
25
- raise "Unknown direction. #{self}"
26
- end
27
-
28
- "Conflict between rule #{reduce.rule.id} and token #{s} #{msg}."
29
- end
30
- end
31
-
32
7
  Conflict = Struct.new(:symbols, :reduce, :type, keyword_init: true)
33
8
 
34
9
  attr_reader :id, :accessing_symbol, :kernels, :conflicts, :resolved_conflicts,
@@ -96,7 +71,7 @@ module Lrama
96
71
  reduce.look_ahead = look_ahead
97
72
  end
98
73
 
99
- # Returns array of [nterm, next_state]
74
+ # Returns array of [Shift, next_state]
100
75
  def nterm_transitions
101
76
  return @nterm_transitions if @nterm_transitions
102
77
 
@@ -111,7 +86,7 @@ module Lrama
111
86
  @nterm_transitions
112
87
  end
113
88
 
114
- # Returns array of [term, next_state]
89
+ # Returns array of [Shift, next_state]
115
90
  def term_transitions
116
91
  return @term_transitions if @term_transitions
117
92
 
@@ -0,0 +1,43 @@
1
+ # TODO: Validate position is not over rule rhs
2
+
3
+ module Lrama
4
+ class States
5
+ class Item < Struct.new(:rule, :position, keyword_init: true)
6
+ # Optimization for States#setup_state
7
+ def hash
8
+ [rule.id, position].hash
9
+ end
10
+
11
+ def rule_id
12
+ rule.id
13
+ end
14
+
15
+ def next_sym
16
+ rule.rhs[position]
17
+ end
18
+
19
+ def end_of_rule?
20
+ rule.rhs.count == position
21
+ end
22
+
23
+ def new_by_next_position
24
+ Item.new(rule: rule, position: position + 1)
25
+ end
26
+
27
+ def previous_sym
28
+ rule.rhs[position - 1]
29
+ end
30
+
31
+ def display_name
32
+ r = rule.rhs.map(&:display_name).insert(position, "•").join(" ")
33
+ "#{r} (rule #{rule.id})"
34
+ end
35
+
36
+ # Right after position
37
+ def display_rest
38
+ r = rule.rhs[position..-1].map(&:display_name).join(" ")
39
+ ". #{r} (rule #{rule.id})"
40
+ end
41
+ end
42
+ end
43
+ end
data/lib/lrama/states.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "forwardable"
2
- require "lrama/report"
2
+ require "lrama/report/duration"
3
+ require "lrama/states/item"
3
4
 
4
5
  module Lrama
5
6
  # States is passed to a template file
@@ -11,46 +12,7 @@ module Lrama
11
12
  include Lrama::Report::Duration
12
13
 
13
14
  def_delegators "@grammar", :symbols, :terms, :nterms, :rules,
14
- :accept_symbol, :eof_symbol, :find_symbol_by_s_value!
15
-
16
- # TODO: Validate position is not over rule rhs
17
- Item = Struct.new(:rule, :position, keyword_init: true) do
18
- # Optimization for States#setup_state
19
- def hash
20
- [rule.id, position].hash
21
- end
22
-
23
- def rule_id
24
- rule.id
25
- end
26
-
27
- def next_sym
28
- rule.rhs[position]
29
- end
30
-
31
- def end_of_rule?
32
- rule.rhs.count == position
33
- end
34
-
35
- def new_by_next_position
36
- Item.new(rule: rule, position: position + 1)
37
- end
38
-
39
- def previous_sym
40
- rule.rhs[position - 1]
41
- end
42
-
43
- def display_name
44
- r = rule.rhs.map(&:display_name).insert(position, "•").join(" ")
45
- "#{r} (rule #{rule.id})"
46
- end
47
-
48
- # Right after position
49
- def display_rest
50
- r = rule.rhs[position..-1].map(&:display_name).join(" ")
51
- ". #{r} (rule #{rule.id})"
52
- end
53
- end
15
+ :accept_symbol, :eof_symbol, :undef_symbol, :find_symbol_by_s_value!
54
16
 
55
17
  attr_reader :states, :reads_relation, :includes_relation, :lookback_relation
56
18
 
data/lib/lrama/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lrama
2
- VERSION = "0.5.1".freeze
2
+ VERSION = "0.5.3".freeze
3
3
  end
data/lrama.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = "LALR (1) parser generator written by Ruby"
10
10
  spec.description = "LALR (1) parser generator written by Ruby"
11
- spec.homepage = "https://github.com/yui-knk/lrama"
11
+ spec.homepage = "https://github.com/ruby/lrama"
12
12
  # See LEGAL.md file for detail
13
- spec.license = "GNU GPLv3"
13
+ spec.license = "GPL-3.0-or-later"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
15
15
 
16
16
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
@@ -0,0 +1,26 @@
1
+ ---
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ revision: 28208148c7e64a25e9b86b9723b4c3a2cef14e81
6
+ remote: https://github.com/ruby/gem_rbs_collection.git
7
+ repo_dir: gems
8
+ path: ".gem_rbs_collection"
9
+ gems:
10
+ - name: erb
11
+ version: '0'
12
+ source:
13
+ type: stdlib
14
+ - name: stackprof
15
+ version: '0.2'
16
+ source:
17
+ type: git
18
+ name: ruby/gem_rbs_collection
19
+ revision: 28208148c7e64a25e9b86b9723b4c3a2cef14e81
20
+ remote: https://github.com/ruby/gem_rbs_collection.git
21
+ repo_dir: gems
22
+ - name: strscan
23
+ version: '0'
24
+ source:
25
+ type: stdlib
26
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,22 @@
1
+ # Download sources
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ remote: https://github.com/ruby/gem_rbs_collection.git
6
+ revision: main
7
+ repo_dir: gems
8
+
9
+ # You can specify local directories as sources also.
10
+ # - type: local
11
+ # path: path/to/your/local/repository
12
+
13
+ # A directory to install the downloaded RBSs
14
+ path: .gem_rbs_collection
15
+
16
+ gems:
17
+ - name: erb
18
+ - name: strscan
19
+ # Skip loading rbs gem's RBS.
20
+ # It's unnecessary if you don't use rbs as a library.
21
+ - name: rbs
22
+ ignore: true
@@ -0,0 +1,11 @@
1
+ module Lrama
2
+ class Report
3
+ module Duration
4
+ self.@_report_duration_enabled: bool | nil
5
+
6
+ def self.enable: -> void
7
+ def self.enabled?: -> bool
8
+ def report_duration: [T] (_ToS method_name) { -> T } -> T
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Lrama
2
+ class Report
3
+ module Profile
4
+ def self.report_profile: { -> void } -> StackProf::result
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module Lrama
2
+ class Warning
3
+ interface _Appendable
4
+ def <<: (String message) -> self
5
+ end
6
+
7
+ @out: _Appendable
8
+
9
+ attr_reader errors: Array[String]
10
+ attr_reader warns: Array[String]
11
+ def initialize: (?_Appendable out) -> void
12
+ def error: (String message) -> void
13
+ def warn: (String message) -> void
14
+ def has_error?: -> bool
15
+ end
16
+ end