lrama 0.1.0 → 0.2.0

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: 1d7cf0f612d3e1ac4aea0b45db6c0533beadd6412f10a85dd17aceefcfb104a9
4
- data.tar.gz: 9e60878988696b8d300700a442cb93bb7d7919be94be80a4bd96cbfe689dad1a
3
+ metadata.gz: 2ba620aa365e3ce11d757da653bd6677ca8bec28ca1b6a5df745d37da6784f59
4
+ data.tar.gz: 2ab03daa03cbb925826f2ca8053dcb04d9648c5c31bd85b1e6fbfe6f9b4cec70
5
5
  SHA512:
6
- metadata.gz: 0fa702fd65a2b84c3d426c45ea6d09a5129391409408604d50767c71f8f2d059db45bbde0b8fd96f093caf3741479add35e8cb1434bdd763c38761f70a994d93
7
- data.tar.gz: d2d5ed81585710107200595b38316120ccc5e01718247c08b6c7de7708ae619de1ec7e37d4ce987b6c21c31d81d5f5c812ecb385d7a6d2838be26e4cf52621f1
6
+ metadata.gz: 05c3e37259997144afe3191d573416c25746c80a7ef0ebc12411f1c126cedf7a8cb8113981c64f1c48e421f517790aa31a14f7ec35ded0f4a7fd4ad83a065e23
7
+ data.tar.gz: 6493c2a94e4681f65f76428c4327dc26be9c14643aadc371400db7def3eb1566f7b4bec091ca719a88c6949d3f46bec0fad87ec73298c69da4906a3c40b28079
data/README.md CHANGED
@@ -14,6 +14,12 @@ Lrama is LALR (1) parser generator written by Ruby. The first goal of this proje
14
14
 
15
15
  ## Installation
16
16
 
17
+ ```shell
18
+ $ gem install lrama
19
+ ```
20
+
21
+ From source codes,
22
+
17
23
  ```shell
18
24
  $ bundle exec rake install
19
25
  $ lrama --version
@@ -23,10 +29,15 @@ $ lrama --version
23
29
  ## Usage
24
30
 
25
31
  ```shell
26
- # "y.tab.c" is generated
27
- $ lrama parse.y
32
+ # "y.tab.c" and "y.tab.h" are generated
33
+ $ lrama -d sample/parse.y
28
34
  ```
29
35
 
36
+ ## Build Ruby
37
+
38
+ 1. Install Lrama
39
+ 2. Run `make YACC=lrama`
40
+
30
41
  ## License
31
42
 
32
43
  See LEGAL.md file.
data/doc/TODO.md CHANGED
@@ -20,6 +20,9 @@
20
20
  * [x] Precedence support
21
21
  * [x] Conflict check
22
22
  * [x] Algorithm Digraph
23
+ * [ ] Conflict resolution
24
+ * [x] Do not generate default action if states have conflicts
25
+ * [ ] Fix number of s/r conflicts of basic.y. See basic.output file generated by Bison.
23
26
  * Rendering
24
27
  * [x] Table compaction
25
28
  * [x] -d option
@@ -41,6 +44,7 @@
41
44
  * [x] Write down something about licenses
42
45
  * Reporting
43
46
  * [ ] Bison style
47
+ * [ ] Wrap not selected reduce with "[]". See basic.output file generated by Bison.
44
48
  * Error Tolerance
45
49
  * [x] Subset of Corchuelo et al.
46
50
  * Lex state
@@ -0,0 +1,29 @@
1
+ module Lrama
2
+ module Bitmap
3
+ def self.from_array(ary)
4
+ bit = 0
5
+
6
+ ary.each do |int|
7
+ bit |= (1 << int)
8
+ end
9
+
10
+ bit
11
+ end
12
+
13
+ def self.to_array(int)
14
+ a = []
15
+ i = 0
16
+
17
+ while int > 0 do
18
+ if int & 1 == 1
19
+ a << i
20
+ end
21
+
22
+ i += 1
23
+ int >>= 1
24
+ end
25
+
26
+ a
27
+ end
28
+ end
29
+ end
data/lib/lrama/command.rb CHANGED
@@ -63,9 +63,10 @@ module Lrama
63
63
 
64
64
  Report::Duration.enable if trace_opts[:time]
65
65
 
66
+ warning = Lrama::Warning.new
66
67
  y = File.read(grammar_file)
67
68
  grammar = Lrama::Parser.new(y).parse
68
- states = Lrama::States.new(grammar, trace_state: (trace_opts[:automaton] || trace_opts[:closure]))
69
+ states = Lrama::States.new(grammar, warning, trace_state: (trace_opts[:automaton] || trace_opts[:closure]))
69
70
  states.compute
70
71
  context = Lrama::Context.new(states)
71
72
 
@@ -87,14 +88,20 @@ module Lrama
87
88
  grammar: grammar,
88
89
  ).render
89
90
  end
91
+
92
+ if warning.has_error?
93
+ exit 1
94
+ end
90
95
  end
91
96
 
92
97
  private
93
98
 
94
99
  def validate_report(report)
95
- list = %w[states itemsets lookaheads solved counterexamples cex all none]
96
- not_supported = %w[counterexamples cex all none]
97
- h = {}
100
+ bison_list = %w[states itemsets lookaheads solved counterexamples cex all none]
101
+ others = %w[verbose]
102
+ list = bison_list + others
103
+ not_supported = %w[counterexamples cex none]
104
+ h = { grammar: true }
98
105
 
99
106
  report.each do |r|
100
107
  if list.include?(r) && !not_supported.include?(r)
@@ -104,6 +111,14 @@ module Lrama
104
111
  end
105
112
  end
106
113
 
114
+ if h[:all]
115
+ (bison_list - not_supported).each do |r|
116
+ h[r.to_sym] = true
117
+ end
118
+
119
+ h.delete(:all)
120
+ end
121
+
107
122
  return h
108
123
  end
109
124
 
data/lib/lrama/context.rb CHANGED
@@ -18,7 +18,7 @@ module Lrama
18
18
  # Array of array
19
19
  @_actions = []
20
20
 
21
- report_duration(:compute_tables) { compute_tables }
21
+ compute_tables
22
22
  end
23
23
 
24
24
  # enum yytokentype
@@ -187,11 +187,11 @@ module Lrama
187
187
  # * yypact_ninf
188
188
  # * yytable_ninf
189
189
  def compute_tables
190
- compute_yydefact
191
- compute_yydefgoto
192
- sort_actions
190
+ report_duration(:compute_yydefact) { compute_yydefact }
191
+ report_duration(:compute_yydefgoto) { compute_yydefgoto }
192
+ report_duration(:sort_actions) { sort_actions }
193
193
  # debug_sorted_actions
194
- compute_packed_table
194
+ report_duration(:compute_packed_table) { compute_packed_table }
195
195
  end
196
196
 
197
197
  def vectors_count
@@ -438,10 +438,11 @@ module Lrama
438
438
  if @table[loc]
439
439
  # If the cell of table is set, can not use the cell.
440
440
  ok = false
441
+ break
441
442
  end
442
443
  end
443
444
 
444
- if userd_res[res]
445
+ if ok && userd_res[res]
445
446
  ok = false
446
447
  end
447
448
 
@@ -0,0 +1,53 @@
1
+ module Lrama
2
+ # Algorithm Digraph of https://dl.acm.org/doi/pdf/10.1145/69622.357187 (P. 625)
3
+ class Digraph
4
+ def initialize(sets, relation, base_function)
5
+ # X in the paper
6
+ @sets = sets
7
+ # R in the paper
8
+ @relation = relation
9
+ # F' in the paper
10
+ @base_function = base_function
11
+ # S in the paper
12
+ @stack = []
13
+ # N in the paper
14
+ @h = Hash.new(0)
15
+ # F in the paper
16
+ @result = {}
17
+ end
18
+
19
+ def compute
20
+ @sets.each do |x|
21
+ next if @h[x] != 0
22
+ traverse(x)
23
+ end
24
+
25
+ return @result
26
+ end
27
+
28
+ private
29
+
30
+ def traverse(x)
31
+ @stack.push(x)
32
+ d = @stack.count
33
+ @h[x] = d
34
+ @result[x] = @base_function[x] # F x = F' x
35
+
36
+ @relation[x] && @relation[x].each do |y|
37
+ traverse(y) if @h[y] == 0
38
+ @h[x] = [@h[x], @h[y]].min
39
+ @result[x] |= @result[y] # F x = F x + F y
40
+ end
41
+
42
+ if @h[x] == d
43
+ while true do
44
+ z = @stack.pop
45
+ @h[z] = Float::INFINITY
46
+ @result[z] = @result[x] # F (Top of S) = F x
47
+
48
+ break if z == x
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/lrama/output.rb CHANGED
@@ -27,14 +27,14 @@ module Lrama
27
27
 
28
28
  def render
29
29
  report_duration(:render) do
30
- erb = ERB.new(File.read(template_file), nil, '-')
30
+ erb = ERB.new(File.read(template_file), trim_mode: '-')
31
31
  erb.filename = template_file
32
32
  tmp = erb.result_with_hash(context: @context, output: self)
33
33
  tmp = replace_special_variables(tmp, @output_file_path)
34
34
  @out << tmp
35
35
 
36
36
  if @header_file_path
37
- erb = ERB.new(File.read(header_template_file), nil, '-')
37
+ erb = ERB.new(File.read(header_template_file), trim_mode: '-')
38
38
  erb.filename = header_template_file
39
39
  tmp = erb.result_with_hash(context: @context, output: self)
40
40
  tmp = replace_special_variables(tmp, @header_file_path)
@@ -135,6 +135,17 @@ module Lrama
135
135
  str
136
136
  end
137
137
 
138
+ # b4_user_initial_action
139
+ def user_initial_action(comment = "")
140
+ return "" unless @grammar.initial_action
141
+
142
+ <<-STR
143
+ #{comment}
144
+ #line #{@grammar.initial_action.line} "#{@grammar_file_path}"
145
+ #{@grammar.initial_action.translated_code}
146
+ STR
147
+ end
148
+
138
149
  # b4_user_actions
139
150
  def user_actions
140
151
  str = ""
@@ -164,10 +175,25 @@ module Lrama
164
175
  str
165
176
  end
166
177
 
178
+ def omit_braces_and_blanks(param)
179
+ param[1..-2].strip
180
+ end
181
+
167
182
  # b4_parse_param
168
183
  def parse_param
169
- # Omit "{}"
170
- @grammar.parse_param[1..-2]
184
+ if @grammar.parse_param
185
+ omit_braces_and_blanks(@grammar.parse_param)
186
+ else
187
+ ""
188
+ end
189
+ end
190
+
191
+ def lex_param
192
+ if @grammar.lex_param
193
+ omit_braces_and_blanks(@grammar.lex_param)
194
+ else
195
+ ""
196
+ end
171
197
  end
172
198
 
173
199
  # b4_user_formals
@@ -179,6 +205,60 @@ module Lrama
179
205
  end
180
206
  end
181
207
 
208
+ # b4_user_args
209
+ def user_args
210
+ if @grammar.parse_param
211
+ ", #{parse_param_name}"
212
+ else
213
+ ""
214
+ end
215
+ end
216
+
217
+ def extract_param_name(param)
218
+ /\A(.)+([a-zA-Z0-9_]+)\z/.match(param)[2]
219
+ end
220
+
221
+ def parse_param_name
222
+ if @grammar.parse_param
223
+ extract_param_name(parse_param)
224
+ else
225
+ ""
226
+ end
227
+ end
228
+
229
+ def lex_param_name
230
+ if @grammar.lex_param
231
+ extract_param_name(lex_param)
232
+ else
233
+ ""
234
+ end
235
+ end
236
+
237
+ # b4_parse_param_use
238
+ def parse_param_use(val, loc)
239
+ str = <<-STR
240
+ YY_USE (#{val});
241
+ YY_USE (#{loc});
242
+ STR
243
+
244
+ if @grammar.parse_param
245
+ str << " YY_USE (#{parse_param_name});"
246
+ end
247
+
248
+ str
249
+ end
250
+
251
+ # b4_yylex_formals
252
+ def yylex_formals
253
+ ary = ["&yylval", "&yylloc"]
254
+
255
+ if @grammar.lex_param
256
+ ary << lex_param_name
257
+ end
258
+
259
+ "(#{ary.join(', ')})"
260
+ end
261
+
182
262
  # b4_table_value_equals
183
263
  def table_value_equals(table, value, literal, symbol)
184
264
  if literal < table.min || table.max < literal
@@ -188,6 +268,17 @@ module Lrama
188
268
  end
189
269
  end
190
270
 
271
+ # b4_yyerror_args
272
+ def yyerror_args
273
+ ary = ["&yylloc"]
274
+
275
+ if @grammar.parse_param
276
+ ary << parse_param_name
277
+ end
278
+
279
+ "#{ary.join(', ')}"
280
+ end
281
+
191
282
  def template_basename
192
283
  File.basename(template_file)
193
284
  end
data/lib/lrama/report.rb CHANGED
@@ -1,6 +1,18 @@
1
1
  module Lrama
2
2
  class Report
3
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
+ #
4
16
  def self.report_profile
5
17
  require "stackprof"
6
18