lrama 0.5.1 → 0.5.3

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