lrama 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecd30d3fab4dd73442ed6d3b2802db5b463159cb6ddf1f1835d9b8e860d4c9dd
4
- data.tar.gz: 79b6087e68d3c2e95db81fa1d25f58280a5543e9c5fa91f5b6ecc7c40b5599d7
3
+ metadata.gz: ce98751a4b4d20c20addf8eebf2a4eb22150b401abbb994941d73f2b2ef81a09
4
+ data.tar.gz: 94b83050b10ec5d01d61093cd2af595e52b3761cc8e86423fa8f30110e44e330
5
5
  SHA512:
6
- metadata.gz: f3302156423399987015deb90afbaa0d6916e5e61b14c5297ff6a0e01ab9db3bbd164b334a11e26d38cf626425b7faee404e5d1cdec236a9b08b576ced4fe201
7
- data.tar.gz: 380d8d31c93e5ae6c5a406c2b2eedad0d4b52dd311ecd742ca1412bd1acade7dae8fe12f7a6325ef8a0b4922ffd927b0dfa2caf3cd54c095669ab2b2cab85516
6
+ metadata.gz: e9e194703ec0b1657389f289b7c4d9cfd13326b1efe25e656080e5260ef2b7f3d4e93fd3d5d49e0934cfb394bc46b994c167a74c3dd2fb2ed3f3ebaaaf31647d
7
+ data.tar.gz: 59e1ed986bbea4ea4a56295d799f6ef5afee24e128fec66bc7ea8184f9bd849aa0807b5995b201e3dda274f6f0f023899a8c287e9a25818dae75c05e5c45cf6a
@@ -124,9 +124,8 @@ jobs:
124
124
  strategy:
125
125
  fail-fast: false
126
126
  matrix:
127
- # '3.0' is the oldest living ruby version
128
- # '2.7' is for BASERUBY
129
- baseruby: ['head', '3.0', '2.7']
127
+ # '3.0' is the oldest living ruby version and minimal BASERUBY version
128
+ baseruby: ['head', '3.0']
130
129
  ruby_branch: ['master']
131
130
  defaults:
132
131
  run:
data/Gemfile CHANGED
@@ -12,6 +12,6 @@ gem "stackprof", platforms: [:ruby] # stackprof doesn't support Windows
12
12
  # Recent steep requires Ruby >= 3.0.0.
13
13
  # Then skip install on some CI jobs.
14
14
  if !ENV['GITHUB_ACTION'] || ENV['INSTALL_STEEP'] == 'true'
15
- gem "rbs", "3.4.1", require: false
15
+ gem "rbs", "3.4.4", require: false
16
16
  gem "steep", "1.6.0", require: false
17
17
  end
data/NEWS.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # NEWS for Lrama
2
2
 
3
+ ## Lrama 0.6.4 (2024-03-22)
4
+
5
+ ### Parameterizing rules (preceded, terminated, delimited)
6
+
7
+ Support `preceded`, `terminated` and `delimited` rules.
8
+
9
+ ```
10
+ program: preceded(opening, X)
11
+
12
+ // Expanded to
13
+
14
+ program: preceded_opening_X
15
+ preceded_opening_X: opening X
16
+ ```
17
+
18
+ ```
19
+ program: terminated(X, closing)
20
+
21
+ // Expanded to
22
+
23
+ program: terminated_X_closing
24
+ terminated_X_closing: X closing
25
+ ```
26
+
27
+ ```
28
+ program: delimited(opening, X, closing)
29
+
30
+ // Expanded to
31
+
32
+ program: delimited_opening_X_closing
33
+ delimited_opening_X_closing: opening X closing
34
+ ```
35
+
36
+ https://github.com/ruby/lrama/pull/382
37
+
38
+ ### Support `%destructor` declaration
39
+
40
+ User can set codes for freeing semantic value resources by using `%destructor`.
41
+ In general, these resources are freed by actions or after parsing.
42
+ However if syntax error happens in parsing, these codes may not be executed.
43
+ Codes associated to `%destructor` are executed when semantic value is popped from the stack by an error.
44
+
45
+ ```
46
+ %token <val1> NUM
47
+ %type <val2> expr2
48
+ %type <val3> expr
49
+
50
+ %destructor {
51
+ printf("destructor for val1: %d\n", $$);
52
+ } <val1> // printer for TAG
53
+
54
+ %destructor {
55
+ printf("destructor for val2: %d\n", $$);
56
+ } <val2>
57
+
58
+ %destructor {
59
+ printf("destructor for expr: %d\n", $$);
60
+ } expr // printer for symbol
61
+ ```
62
+
63
+ Bison supports this feature from 1.75b.
64
+
65
+ https://github.com/ruby/lrama/pull/385
66
+
3
67
  ## Lrama 0.6.3 (2024-02-15)
4
68
 
5
69
  ### Bring Your Own Stack
@@ -34,6 +98,8 @@ primary: k_if expr_value then compstmt if_tail k_end
34
98
  }
35
99
  ```
36
100
 
101
+ https://github.com/ruby/lrama/pull/367
102
+
37
103
  ## Lrama 0.6.2 (2024-01-27)
38
104
 
39
105
  ### %no-stdlib directive
@@ -51,7 +117,7 @@ Allow to pass an instantiated rule to other parameterizing rules.
51
117
 
52
118
  ```
53
119
  %rule constant(X) : X
54
- ;
120
+ ;
55
121
 
56
122
  %rule option(Y) : /* empty */
57
123
  | Y
data/Steepfile CHANGED
@@ -5,6 +5,7 @@ target :lib do
5
5
  signature "sig"
6
6
 
7
7
  check "lib/lrama/grammar/binding.rb"
8
+ check "lib/lrama/grammar/code/destructor_code.rb"
8
9
  check "lib/lrama/grammar/code/printer_code.rb"
9
10
  check "lib/lrama/grammar/code.rb"
10
11
  check "lib/lrama/grammar/counter.rb"
@@ -14,6 +15,7 @@ target :lib do
14
15
  check "lib/lrama/grammar/symbols"
15
16
  check "lib/lrama/grammar/percent_code.rb"
16
17
  check "lib/lrama/grammar/precedence.rb"
18
+ check "lib/lrama/grammar/destructor.rb"
17
19
  check "lib/lrama/grammar/printer.rb"
18
20
  check "lib/lrama/grammar/reference.rb"
19
21
  check "lib/lrama/grammar/rule_builder.rb"
@@ -23,5 +25,6 @@ target :lib do
23
25
  check "lib/lrama/report"
24
26
  check "lib/lrama/bitmap.rb"
25
27
  check "lib/lrama/digraph.rb"
28
+ check "lib/lrama/options.rb"
26
29
  check "lib/lrama/warning.rb"
27
30
  end
@@ -0,0 +1,40 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Code
4
+ class DestructorCode < Code
5
+ def initialize(type:, token_code:, tag:)
6
+ super(type: type, token_code: token_code)
7
+ @tag = tag
8
+ end
9
+
10
+ private
11
+
12
+ # * ($$) *yyvaluep
13
+ # * (@$) *yylocationp
14
+ # * ($:$) error
15
+ # * ($1) error
16
+ # * (@1) error
17
+ # * ($:1) error
18
+ def reference_to_c(ref)
19
+ case
20
+ when ref.type == :dollar && ref.name == "$" # $$
21
+ member = @tag.member
22
+ "((*yyvaluep).#{member})"
23
+ when ref.type == :at && ref.name == "$" # @$
24
+ "(*yylocationp)"
25
+ when ref.type == :index && ref.name == "$" # $:$
26
+ raise "$:#{ref.value} can not be used in #{type}."
27
+ when ref.type == :dollar # $n
28
+ raise "$#{ref.value} can not be used in #{type}."
29
+ when ref.type == :at # @n
30
+ raise "@#{ref.value} can not be used in #{type}."
31
+ when ref.type == :index # $:n
32
+ raise "$:#{ref.value} can not be used in #{type}."
33
+ else
34
+ raise "Unexpected. #{self}, #{ref}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,4 +1,5 @@
1
1
  require "forwardable"
2
+ require "lrama/grammar/code/destructor_code"
2
3
  require "lrama/grammar/code/initial_action_code"
3
4
  require "lrama/grammar/code/no_reference_code"
4
5
  require "lrama/grammar/code/printer_code"
@@ -0,0 +1,9 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Destructor < Struct.new(:ident_or_tags, :token_code, :lineno, keyword_init: true)
4
+ def translated_code(tag)
5
+ Code::DestructorCode.new(type: :destructor, token_code: token_code, tag: tag).translated_code
6
+ end
7
+ end
8
+ end
9
+ end
@@ -115,12 +115,12 @@ module Lrama
115
115
  @replaced_rhs << lhs_token
116
116
  parameterizing_rule_resolver.created_lhs_list << lhs_token
117
117
  parameterizing_rule.rhs_list.each do |r|
118
- rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
118
+ rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
119
119
  rule_builder.lhs = lhs_token
120
120
  r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
121
121
  rule_builder.line = line
122
- rule_builder.user_code = r.user_code
123
122
  rule_builder.precedence_sym = r.precedence_sym
123
+ rule_builder.user_code = r.user_code
124
124
  rule_builder.complete_input
125
125
  rule_builder.setup_rules(parameterizing_rule_resolver)
126
126
  @rule_builders_for_parameterizing_rules << rule_builder
@@ -8,6 +8,9 @@
8
8
 
9
9
  **********************************************************************/
10
10
 
11
+ // -------------------------------------------------------------------
12
+ // Options
13
+
11
14
  /*
12
15
  * program: option(number)
13
16
  *
@@ -21,6 +24,45 @@
21
24
  | X
22
25
  ;
23
26
 
27
+ // -------------------------------------------------------------------
28
+ // Sequences
29
+
30
+ /*
31
+ * program: preceded(opening, X)
32
+ *
33
+ * =>
34
+ *
35
+ * program: preceded_opening_X
36
+ * preceded_opening_X: opening X
37
+ */
38
+ %rule preceded(opening, X): opening X { $$ = $2; }
39
+ ;
40
+
41
+ /*
42
+ * program: terminated(X, closing)
43
+ *
44
+ * =>
45
+ *
46
+ * program: terminated_X_closing
47
+ * terminated_X_closing: X closing
48
+ */
49
+ %rule terminated(X, closing): X closing { $$ = $1; }
50
+ ;
51
+
52
+ /*
53
+ * program: delimited(opening, X, closing)
54
+ *
55
+ * =>
56
+ *
57
+ * program: delimited_opening_X_closing
58
+ * delimited_opening_X_closing: opening X closing
59
+ */
60
+ %rule delimited(opening, X, closing): opening X closing { $$ = $2; }
61
+ ;
62
+
63
+ // -------------------------------------------------------------------
64
+ // Lists
65
+
24
66
  /*
25
67
  * program: list(number)
26
68
  *
@@ -7,11 +7,12 @@
7
7
  module Lrama
8
8
  class Grammar
9
9
  class Symbol
10
- attr_accessor :id, :alias_name, :tag, :number, :token_id, :nullable, :precedence, :printer, :error_token, :first_set, :first_set_bitmap
10
+ attr_accessor :id, :alias_name, :tag, :number, :token_id, :nullable, :precedence,
11
+ :printer, :destructor, :error_token, :first_set, :first_set_bitmap
11
12
  attr_reader :term
12
13
  attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol
13
14
 
14
- def initialize(id:, term:, alias_name: nil, number: nil, tag: nil, token_id: nil, nullable: nil, precedence: nil, printer: nil)
15
+ def initialize(id:, term:, alias_name: nil, number: nil, tag: nil, token_id: nil, nullable: nil, precedence: nil, printer: nil, destructor: nil)
15
16
  @id = id
16
17
  @alias_name = alias_name
17
18
  @number = number
@@ -21,6 +22,7 @@ module Lrama
21
22
  @nullable = nullable
22
23
  @precedence = precedence
23
24
  @printer = printer
25
+ @destructor = destructor
24
26
  end
25
27
 
26
28
  def term?
@@ -58,7 +58,7 @@ module Lrama
58
58
  end
59
59
 
60
60
  def find_symbol_by_s_value!(s_value)
61
- find_symbol_by_s_value(s_value) || (raise "Symbol not found: #{s_value}")
61
+ find_symbol_by_s_value(s_value) || (raise "Symbol not found. value: `#{s_value}`")
62
62
  end
63
63
 
64
64
  def find_symbol_by_id(id)
@@ -68,7 +68,7 @@ module Lrama
68
68
  end
69
69
 
70
70
  def find_symbol_by_id!(id)
71
- find_symbol_by_id(id) || (raise "Symbol not found: #{id}")
71
+ find_symbol_by_id(id) || (raise "Symbol not found. #{id}")
72
72
  end
73
73
 
74
74
  def find_symbol_by_token_id(token_id)
@@ -78,7 +78,7 @@ module Lrama
78
78
  def find_symbol_by_number!(number)
79
79
  sym = symbols[number]
80
80
 
81
- raise "Symbol not found: #{number}" unless sym
81
+ raise "Symbol not found. number: `#{number}`" unless sym
82
82
  raise "[BUG] Symbol number mismatch. #{number}, #{sym}" if sym.number != number
83
83
 
84
84
  sym
@@ -118,6 +118,23 @@ module Lrama
118
118
  end
119
119
  end
120
120
 
121
+ def fill_destructor(destructors)
122
+ symbols.each do |sym|
123
+ destructors.each do |destructor|
124
+ destructor.ident_or_tags.each do |ident_or_tag|
125
+ case ident_or_tag
126
+ when Lrama::Lexer::Token::Ident
127
+ sym.destructor = destructor if sym.id == ident_or_tag
128
+ when Lrama::Lexer::Token::Tag
129
+ sym.destructor = destructor if sym.tag == ident_or_tag
130
+ else
131
+ raise "Unknown token type. #{destructor}"
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
121
138
  def fill_error_token(error_tokens)
122
139
  symbols.each do |sym|
123
140
  error_tokens.each do |token|
@@ -154,7 +171,7 @@ module Lrama
154
171
  def find_nterm_by_id!(id)
155
172
  @nterms.find do |s|
156
173
  s.id == id
157
- end || (raise "Symbol not found: #{id}")
174
+ end || (raise "Symbol not found. #{id}")
158
175
  end
159
176
 
160
177
  def fill_terms_number
data/lib/lrama/grammar.rb CHANGED
@@ -3,6 +3,7 @@ require "lrama/grammar/auxiliary"
3
3
  require "lrama/grammar/binding"
4
4
  require "lrama/grammar/code"
5
5
  require "lrama/grammar/counter"
6
+ require "lrama/grammar/destructor"
6
7
  require "lrama/grammar/error_token"
7
8
  require "lrama/grammar/parameterizing_rule"
8
9
  require "lrama/grammar/percent_code"
@@ -34,7 +35,7 @@ module Lrama
34
35
  def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
35
36
  :find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
36
37
  :find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
37
- :fill_printer, :fill_error_token, :sort_by_number!
38
+ :fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!
38
39
 
39
40
 
40
41
  def initialize(rule_counter)
@@ -43,6 +44,7 @@ module Lrama
43
44
  # Code defined by "%code"
44
45
  @percent_codes = []
45
46
  @printers = []
47
+ @destructors = []
46
48
  @error_tokens = []
47
49
  @symbols_resolver = Grammar::Symbols::Resolver.new
48
50
  @types = []
@@ -65,6 +67,10 @@ module Lrama
65
67
  @percent_codes << PercentCode.new(id.s_value, code.s_value)
66
68
  end
67
69
 
70
+ def add_destructor(ident_or_tags:, token_code:, lineno:)
71
+ @destructors << Destructor.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
72
+ end
73
+
68
74
  def add_printer(ident_or_tags:, token_code:, lineno:)
69
75
  @printers << Printer.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
70
76
  end
@@ -345,6 +351,7 @@ module Lrama
345
351
  fill_symbol_number
346
352
  fill_nterm_type(@types)
347
353
  fill_printer(@printers)
354
+ fill_destructor(@destructors)
348
355
  fill_error_token(@error_tokens)
349
356
  sort_by_number!
350
357
  end
@@ -18,7 +18,7 @@ module Lrama
18
18
  end
19
19
 
20
20
  def to_s
21
- "#{super} location: #{location}"
21
+ "value: `#{s_value}`, location: #{location}"
22
22
  end
23
23
 
24
24
  def referred_by?(string)
data/lib/lrama/lexer.rb CHANGED
@@ -21,6 +21,7 @@ module Lrama
21
21
  %define
22
22
  %require
23
23
  %printer
24
+ %destructor
24
25
  %lex-param
25
26
  %parse-param
26
27
  %initial-action
@@ -64,9 +64,18 @@ module Lrama
64
64
  o.on('-H', '--header=[FILE]', 'also produce a header file named FILE') {|v| @options.header = true; @options.header_file = v }
65
65
  o.on('-d', 'also produce a header file') { @options.header = true }
66
66
  o.on('-r', '--report=THINGS', Array, 'also produce details on the automaton') {|v| @report = v }
67
+ o.on_tail ''
68
+ o.on_tail 'Valid Reports:'
69
+ o.on_tail " #{VALID_REPORTS.join(' ')}"
70
+
67
71
  o.on('--report-file=FILE', 'also produce details on the automaton output to a file named FILE') {|v| @options.report_file = v }
68
72
  o.on('-o', '--output=FILE', 'leave output to FILE') {|v| @options.outfile = v }
73
+
69
74
  o.on('--trace=THINGS', Array, 'also output trace logs at runtime') {|v| @trace = v }
75
+ o.on_tail ''
76
+ o.on_tail 'Valid Traces:'
77
+ o.on_tail " #{VALID_TRACES.join(' ')}"
78
+
70
79
  o.on('-v', 'reserved, do nothing') { }
71
80
  o.separator ''
72
81
  o.separator 'Error Recovery:'
@@ -75,20 +84,22 @@ module Lrama
75
84
  o.separator 'Other options:'
76
85
  o.on('-V', '--version', "output version information and exit") {|v| puts "lrama #{Lrama::VERSION}"; exit 0 }
77
86
  o.on('-h', '--help', "display this help and exit") {|v| puts o; exit 0 }
78
- o.separator ''
87
+ o.on_tail
79
88
  o.parse!(argv)
80
89
  end
81
90
  end
82
91
 
92
+ BISON_REPORTS = %w[states itemsets lookaheads solved counterexamples cex all none]
93
+ OTHER_REPORTS = %w[verbose]
94
+ NOT_SUPPORTED_REPORTS = %w[cex none]
95
+ VALID_REPORTS = BISON_REPORTS + OTHER_REPORTS - NOT_SUPPORTED_REPORTS
96
+
83
97
  def validate_report(report)
84
- bison_list = %w[states itemsets lookaheads solved counterexamples cex all none]
85
- others = %w[verbose]
86
- list = bison_list + others
87
- not_supported = %w[cex none]
98
+ list = VALID_REPORTS
88
99
  h = { grammar: true }
89
100
 
90
101
  report.each do |r|
91
- if list.include?(r) && !not_supported.include?(r)
102
+ if list.include?(r)
92
103
  h[r.to_sym] = true
93
104
  else
94
105
  raise "Invalid report option \"#{r}\"."
@@ -96,7 +107,7 @@ module Lrama
96
107
  end
97
108
 
98
109
  if h[:all]
99
- (bison_list - not_supported).each do |r|
110
+ (BISON_REPORTS - NOT_SUPPORTED_REPORTS).each do |r|
100
111
  h[r.to_sym] = true
101
112
  end
102
113
 
@@ -106,12 +117,14 @@ module Lrama
106
117
  return h
107
118
  end
108
119
 
120
+ VALID_TRACES = %w[
121
+ none locations scan parse automaton bitsets
122
+ closure grammar rules resource sets muscles tools
123
+ m4-early m4 skeleton time ielr cex all
124
+ ]
125
+
109
126
  def validate_trace(trace)
110
- list = %w[
111
- none locations scan parse automaton bitsets
112
- closure grammar rules resource sets muscles tools
113
- m4-early m4 skeleton time ielr cex all
114
- ]
127
+ list = VALID_TRACES
115
128
  h = {}
116
129
 
117
130
  trace.each do |t|
data/lib/lrama/options.rb CHANGED
@@ -18,6 +18,7 @@ module Lrama
18
18
  @trace_opts = nil
19
19
  @report_opts = nil
20
20
  @y = STDIN
21
+ @debug = false
21
22
  end
22
23
  end
23
24
  end
data/lib/lrama/output.rb CHANGED
@@ -150,6 +150,25 @@ module Lrama
150
150
  str
151
151
  end
152
152
 
153
+ def symbol_actions_for_destructor
154
+ str = ""
155
+
156
+ @grammar.symbols.each do |sym|
157
+ next unless sym.destructor
158
+
159
+ str << <<-STR
160
+ case #{sym.enum_name}: /* #{sym.comment} */
161
+ #line #{sym.destructor.lineno} "#{@grammar_file_path}"
162
+ {#{sym.destructor.translated_code(sym.tag)}}
163
+ #line [@oline@] [@ofile@]
164
+ break;
165
+
166
+ STR
167
+ end
168
+
169
+ str
170
+ end
171
+
153
172
  # b4_user_initial_action
154
173
  def user_initial_action(comment = "")
155
174
  return "" unless @grammar.initial_action