lrama 0.5.5 → 0.5.7

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/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lrama
2
- VERSION = "0.5.5".freeze
2
+ VERSION = "0.5.7".freeze
3
3
  end
data/lib/lrama.rb CHANGED
@@ -5,6 +5,8 @@ require "lrama/counterexamples"
5
5
  require "lrama/digraph"
6
6
  require "lrama/grammar"
7
7
  require "lrama/lexer"
8
+ require "lrama/option_parser"
9
+ require "lrama/options"
8
10
  require "lrama/output"
9
11
  require "lrama/parser"
10
12
  require "lrama/report"
data/parser.y ADDED
@@ -0,0 +1,416 @@
1
+ class Lrama::Parser
2
+ rule
3
+ input: prologue_declarations bison_declarations "%%" grammar epilogue_opt
4
+
5
+ prologue_declarations: # empty
6
+ | prologue_declarations prologue_declaration
7
+
8
+ prologue_declaration: "%{"
9
+ {
10
+ @lexer.status = :c_declaration
11
+ @lexer.end_symbol = '%}'
12
+ @grammar.prologue_first_lineno = @lexer.line
13
+ }
14
+ C_DECLARATION
15
+ {
16
+ @lexer.status = :initial
17
+ @lexer.end_symbol = nil
18
+ }
19
+ "%}"
20
+ {
21
+ @grammar.prologue = val[2].s_value
22
+ }
23
+ | "%require" STRING
24
+
25
+ bison_declarations: /* empty */ { result = "" }
26
+ | bison_declarations bison_declaration
27
+
28
+ bison_declaration: grammar_declaration
29
+ | "%expect" INTEGER { @grammar.expect = val[1] }
30
+ | "%define" variable value
31
+ | "%require" STRING
32
+ | "%param" params
33
+ | "%lex-param" params
34
+ {
35
+ val[1].each {|token|
36
+ token.references = []
37
+ @grammar.lex_param = @grammar.build_code(:lex_param, token).token_code.s_value
38
+ }
39
+ }
40
+ | "%parse-param" params
41
+ {
42
+ val[1].each {|token|
43
+ token.references = []
44
+ @grammar.parse_param = @grammar.build_code(:parse_param, token).token_code.s_value
45
+ }
46
+ }
47
+ | "%initial-action" "{"
48
+ {
49
+ @lexer.status = :c_declaration
50
+ @lexer.end_symbol = '}'
51
+ }
52
+ C_DECLARATION
53
+ {
54
+ @lexer.status = :initial
55
+ @lexer.end_symbol = nil
56
+ }
57
+ "}"
58
+ {
59
+ @grammar.initial_action = @grammar.build_code(:initial_action, val[3])
60
+ }
61
+ | ";"
62
+
63
+ grammar_declaration: "%union" "{"
64
+ {
65
+ @lexer.status = :c_declaration
66
+ @lexer.end_symbol = '}'
67
+ }
68
+ C_DECLARATION
69
+ {
70
+ @lexer.status = :initial
71
+ @lexer.end_symbol = nil
72
+ }
73
+ "}"
74
+ {
75
+ @grammar.set_union(@grammar.build_code(:union, val[3]), val[3].line)
76
+ }
77
+ | symbol_declaration
78
+ | "%destructor" "{"
79
+ {
80
+ @lexer.status = :c_declaration
81
+ @lexer.end_symbol = '}'
82
+ }
83
+ C_DECLARATION
84
+ {
85
+ @lexer.status = :initial
86
+ @lexer.end_symbol = nil
87
+ }
88
+ "}" generic_symlist
89
+ | "%printer" "{"
90
+ {
91
+ @lexer.status = :c_declaration
92
+ @lexer.end_symbol = '}'
93
+ }
94
+ C_DECLARATION
95
+ {
96
+ @lexer.status = :initial
97
+ @lexer.end_symbol = nil
98
+ }
99
+ "}" generic_symlist
100
+ {
101
+ @grammar.add_printer(ident_or_tags: val[6], code: @grammar.build_code(:printer, val[3]), lineno: val[3].line)
102
+ }
103
+ | "%error-token" "{"
104
+ {
105
+ @lexer.status = :c_declaration
106
+ @lexer.end_symbol = '}'
107
+ }
108
+ C_DECLARATION
109
+ {
110
+ @lexer.status = :initial
111
+ @lexer.end_symbol = nil
112
+ }
113
+ "}" generic_symlist
114
+ {
115
+ @grammar.add_error_token(ident_or_tags: val[6], code: @grammar.build_code(:error_token, val[3]), lineno: val[3].line)
116
+ }
117
+
118
+ symbol_declaration: "%token" token_declarations
119
+ | "%type" symbol_declarations
120
+ {
121
+ val[1].each {|hash|
122
+ hash[:tokens].each {|id|
123
+ @grammar.add_type(id: id, tag: hash[:tag])
124
+ }
125
+ }
126
+ }
127
+ | "%left" token_declarations_for_precedence
128
+ {
129
+ val[1].each {|hash|
130
+ hash[:tokens].each {|id|
131
+ sym = @grammar.add_term(id: id)
132
+ @grammar.add_left(sym, @precedence_number)
133
+ }
134
+ }
135
+ @precedence_number += 1
136
+ }
137
+ | "%right" token_declarations_for_precedence
138
+ {
139
+ val[1].each {|hash|
140
+ hash[:tokens].each {|id|
141
+ sym = @grammar.add_term(id: id)
142
+ @grammar.add_right(sym, @precedence_number)
143
+ }
144
+ }
145
+ @precedence_number += 1
146
+ }
147
+ | "%precedence" token_declarations_for_precedence
148
+ {
149
+ val[1].each {|hash|
150
+ hash[:tokens].each {|id|
151
+ sym = @grammar.add_term(id: id)
152
+ @grammar.add_precedence(sym, @precedence_number)
153
+ }
154
+ }
155
+ @precedence_number += 1
156
+ }
157
+ | "%nonassoc" token_declarations_for_precedence
158
+ {
159
+ val[1].each {|hash|
160
+ hash[:tokens].each {|id|
161
+ sym = @grammar.add_term(id: id)
162
+ @grammar.add_nonassoc(sym, @precedence_number)
163
+ }
164
+ }
165
+ @precedence_number += 1
166
+ }
167
+
168
+ token_declarations: token_declaration_list
169
+ {
170
+ val[0].each {|token_declaration|
171
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: nil, replace: true)
172
+ }
173
+ }
174
+ | TAG token_declaration_list
175
+ {
176
+ val[1].each {|token_declaration|
177
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[0], replace: true)
178
+ }
179
+ }
180
+ | token_declarations TAG token_declaration_list
181
+ {
182
+ val[2].each {|token_declaration|
183
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[1], replace: true)
184
+ }
185
+ }
186
+
187
+ token_declaration_list: token_declaration { result = [val[0]] }
188
+ | token_declaration_list token_declaration { result = val[0].append(val[1]) }
189
+
190
+ token_declaration: id int_opt alias { result = val }
191
+
192
+ int_opt: # empty
193
+ | INTEGER
194
+
195
+ alias: # empty
196
+ | STRING # TODO: change this to string_as_id
197
+
198
+ symbol_declarations: symbol_declaration_list
199
+ {
200
+ result = [{tag: nil, tokens: val[0]}]
201
+ }
202
+ | TAG symbol_declaration_list
203
+ {
204
+ result = [{tag: val[0], tokens: val[1]}]
205
+ }
206
+ | symbol_declarations TAG symbol_declaration_list
207
+ {
208
+ result = val[0].append({tag: val[1], tokens: val[2]})
209
+ }
210
+
211
+ symbol_declaration_list: symbol { result = [val[0]] }
212
+ | symbol_declaration_list symbol { result = val[0].append(val[1]) }
213
+
214
+ symbol: id
215
+ | string_as_id
216
+
217
+ params: params "{"
218
+ {
219
+ @lexer.status = :c_declaration
220
+ @lexer.end_symbol = '}'
221
+ }
222
+ C_DECLARATION
223
+ {
224
+ @lexer.status = :initial
225
+ @lexer.end_symbol = nil
226
+ }
227
+ "}"
228
+ {
229
+ result = val[0].append(val[3])
230
+ }
231
+ | "{"
232
+ {
233
+ @lexer.status = :c_declaration
234
+ @lexer.end_symbol = '}'
235
+ }
236
+ C_DECLARATION
237
+ {
238
+ @lexer.status = :initial
239
+ @lexer.end_symbol = nil
240
+ }
241
+ "}"
242
+ {
243
+ result = [val[2]]
244
+ }
245
+
246
+ token_declarations_for_precedence: token_declaration_list_for_precedence
247
+ {
248
+ result = [{tag: nil, tokens: val[0]}]
249
+ }
250
+ | TAG token_declaration_list_for_precedence
251
+ {
252
+ result = [{tag: val[0], tokens: val[1]}]
253
+ }
254
+ | token_declarations_for_precedence token_declaration_list_for_precedence
255
+ {
256
+ result = val[0].append({tag: nil, tokens: val[1]})
257
+ }
258
+
259
+ token_declaration_list_for_precedence: token_declaration_for_precedence { result = [val[0]] }
260
+ | token_declaration_list_for_precedence token_declaration_for_precedence { result = val[0].append(val[1]) }
261
+
262
+ token_declaration_for_precedence: id
263
+
264
+ id: IDENTIFIER { raise "Ident after %prec" if @prec_seen }
265
+ | CHARACTER { raise "Char after %prec" if @prec_seen }
266
+
267
+ grammar: rules_or_grammar_declaration
268
+ | grammar rules_or_grammar_declaration
269
+
270
+ rules_or_grammar_declaration: rules
271
+ | grammar_declaration ";"
272
+
273
+ rules: id_colon named_ref_opt ":" rhs_list
274
+ {
275
+ lhs = val[0]
276
+ lhs.alias = val[1]
277
+ val[3].each {|hash|
278
+ @grammar.add_rule(lhs: lhs, rhs: hash[:rhs], lineno: hash[:lineno])
279
+ }
280
+ }
281
+
282
+ rhs_list: rhs
283
+ {
284
+ result = [{rhs: val[0], lineno: val[0].first&.line || @lexer.line - 1}]
285
+ }
286
+ | rhs_list "|" rhs
287
+ {
288
+ result = val[0].append({rhs: val[2], lineno: val[2].first&.line || @lexer.line - 1})
289
+ }
290
+ | rhs_list ";"
291
+
292
+ rhs: /* empty */
293
+ {
294
+ result = []
295
+ @prec_seen = false
296
+ @code_after_prec = false
297
+ }
298
+ | rhs symbol named_ref_opt
299
+ {
300
+ token = val[1]
301
+ val[1].alias = val[2]
302
+ result = val[0].append(token)
303
+ }
304
+ | rhs "{"
305
+ {
306
+ if @prec_seen
307
+ raise "Multiple User_code after %prec" if @code_after_prec
308
+ @code_after_prec = true
309
+ end
310
+ @lexer.status = :c_declaration
311
+ @lexer.end_symbol = '}'
312
+ }
313
+ C_DECLARATION
314
+ {
315
+ @lexer.status = :initial
316
+ @lexer.end_symbol = nil
317
+ }
318
+ "}" named_ref_opt
319
+ {
320
+ token = val[3]
321
+ token.alias = val[6]
322
+ result = val[0].append(token)
323
+ }
324
+ | "{"
325
+ {
326
+ if @prec_seen
327
+ raise "Multiple User_code after %prec" if @code_after_prec
328
+ @code_after_prec = true
329
+ end
330
+ @lexer.status = :c_declaration
331
+ @lexer.end_symbol = '}'
332
+ }
333
+ C_DECLARATION
334
+ {
335
+ @lexer.status = :initial
336
+ @lexer.end_symbol = nil
337
+ }
338
+ "}" named_ref_opt
339
+ {
340
+ token = val[2]
341
+ token.alias = val[5]
342
+ result = [token]
343
+ }
344
+ | rhs "%prec" symbol
345
+ {
346
+ sym = @grammar.find_symbol_by_id!(val[2])
347
+ result = val[0].append(sym)
348
+ @prec_seen = true
349
+ }
350
+
351
+ named_ref_opt: # empty
352
+ | '[' IDENTIFIER ']' { result = val[1].s_value }
353
+
354
+ id_colon: IDENT_COLON
355
+
356
+ epilogue_opt: # empty
357
+ | "%%"
358
+ {
359
+ @lexer.status = :c_declaration
360
+ @lexer.end_symbol = '\Z'
361
+ @grammar.epilogue_first_lineno = @lexer.line + 1
362
+ }
363
+ C_DECLARATION
364
+ {
365
+ @lexer.status = :initial
366
+ @lexer.end_symbol = nil
367
+ @grammar.epilogue = val[2].s_value
368
+ }
369
+
370
+ variable: id
371
+
372
+ value: # empty
373
+ | IDENTIFIER
374
+ | STRING
375
+ | "{...}"
376
+
377
+ generic_symlist: generic_symlist_item { result = [val[0]] }
378
+ | generic_symlist generic_symlist_item { result = val[0].append(val[1]) }
379
+
380
+ generic_symlist_item: symbol
381
+ | TAG
382
+
383
+ string_as_id: STRING { result = Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Ident, s_value: val[0]) }
384
+ end
385
+
386
+ ---- inner
387
+
388
+ include Lrama::Report::Duration
389
+
390
+ def initialize(text)
391
+ @text = text
392
+ end
393
+
394
+ def parse
395
+ report_duration(:parse) do
396
+ @lexer = Lrama::Lexer.new(@text)
397
+ @grammar = Lrama::Grammar.new
398
+ @precedence_number = 0
399
+ do_parse
400
+ @grammar.extract_references
401
+ @grammar.prepare
402
+ @grammar.compute_nullable
403
+ @grammar.compute_first_set
404
+ @grammar.validate!
405
+ @grammar
406
+ end
407
+ end
408
+
409
+ def next_token
410
+ @lexer.next_token
411
+ end
412
+
413
+ def on_error(error_token_id, error_value, value_stack)
414
+ raise ParseError, sprintf("\n%d:%d: parse error on value %s (%s)",
415
+ @lexer.line, @lexer.column, error_value.inspect, token_to_str(error_token_id) || '?')
416
+ end
@@ -2,7 +2,7 @@
2
2
  sources:
3
3
  - type: git
4
4
  name: ruby/gem_rbs_collection
5
- revision: 28208148c7e64a25e9b86b9723b4c3a2cef14e81
5
+ revision: 95ad664324500c9eec78569b45da98c65a27a511
6
6
  remote: https://github.com/ruby/gem_rbs_collection.git
7
7
  repo_dir: gems
8
8
  path: ".gem_rbs_collection"
data/sample/calc.y CHANGED
@@ -16,8 +16,6 @@
16
16
  #include <stdlib.h>
17
17
  #include <ctype.h>
18
18
 
19
- #include "calc.h"
20
-
21
19
  static int yylex(YYSTYPE *val, YYLTYPE *loc);
22
20
  static int yyerror(YYLTYPE *loc, const char *str);
23
21
  %}
data/sample/parse.y CHANGED
@@ -4,9 +4,6 @@
4
4
 
5
5
  %{
6
6
  // Prologue
7
-
8
- #include "y.tab.h"
9
-
10
7
  static enum yytokentype yylex(YYSTYPE *lval, YYLTYPE *yylloc);
11
8
  static void yyerror(YYLTYPE *yylloc, const char *msg);
12
9
 
@@ -0,0 +1,23 @@
1
+ module Lrama
2
+ class Digraph
3
+ def initialize: (Array[Integer] sets, Hash[Integer, Array[Integer]] relation, Hash[Integer, Integer] base_function) -> void
4
+ # X in the paper
5
+ @sets: Array[Integer]
6
+ # R in the paper
7
+ @relation: Hash[Integer, Array[Integer]]
8
+ # F' in the paper
9
+ @base_function: Hash[Integer, Integer]
10
+ # S in the paper
11
+ @stack: Array[Integer]
12
+ # N in the paper
13
+ @h: Hash[Integer, (Integer|Float)?]
14
+ # F in the paper
15
+ @result: Hash[Integer, Integer]
16
+
17
+ def compute: () -> Hash[Integer, Integer]
18
+
19
+ private
20
+
21
+ def traverse: (Integer x) -> void
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Lrama
2
+ class Lexer
3
+ class Token
4
+ attr_accessor type: Type
5
+ attr_accessor s_value: String
6
+ attr_accessor alias: String
7
+
8
+ def initialize: (?type: Type, ?s_value: String, ?alias: String) -> void
9
+ class Type
10
+ attr_accessor id: Integer
11
+ attr_accessor name: String
12
+
13
+ def initialize: (?id: Integer, ?name: String) -> void
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,71 @@
1
+ <%# b4_shared_declarations -%>
2
+ <%-# b4_cpp_guard_open([b4_spec_mapped_header_file]) -%>
3
+ <%- if output.spec_mapped_header_file -%>
4
+ #ifndef <%= output.b4_cpp_guard__b4_spec_mapped_header_file %>
5
+ # define <%= output.b4_cpp_guard__b4_spec_mapped_header_file %>
6
+ <%- end -%>
7
+ <%-# b4_declare_yydebug & b4_YYDEBUG_define -%>
8
+ /* Debug traces. */
9
+ #ifndef YYDEBUG
10
+ # define YYDEBUG 0
11
+ #endif
12
+ #if YYDEBUG && !defined(yydebug)
13
+ extern int yydebug;
14
+ #endif
15
+ <%-# b4_percent_code_get([[requires]]). %code is not supported -%>
16
+
17
+ <%-# b4_token_enums_defines -%>
18
+ /* Token kinds. */
19
+ #ifndef YYTOKENTYPE
20
+ # define YYTOKENTYPE
21
+ enum yytokentype
22
+ {
23
+ <%= output.token_enums -%>
24
+ };
25
+ typedef enum yytokentype yytoken_kind_t;
26
+ #endif
27
+
28
+ <%-# b4_declare_yylstype -%>
29
+ <%-# b4_value_type_define -%>
30
+ /* Value type. */
31
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
32
+ union YYSTYPE
33
+ {
34
+ #line <%= output.grammar.union.lineno %> "<%= output.grammar_file_path %>"
35
+ <%= output.grammar.union.braces_less_code %>
36
+ #line [@oline@] [@ofile@]
37
+
38
+ };
39
+ typedef union YYSTYPE YYSTYPE;
40
+ # define YYSTYPE_IS_TRIVIAL 1
41
+ # define YYSTYPE_IS_DECLARED 1
42
+ #endif
43
+
44
+ <%-# b4_location_type_define -%>
45
+ /* Location type. */
46
+ #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
47
+ typedef struct YYLTYPE YYLTYPE;
48
+ struct YYLTYPE
49
+ {
50
+ int first_line;
51
+ int first_column;
52
+ int last_line;
53
+ int last_column;
54
+ };
55
+ # define YYLTYPE_IS_DECLARED 1
56
+ # define YYLTYPE_IS_TRIVIAL 1
57
+ #endif
58
+
59
+
60
+
61
+
62
+ <%-# b4_declare_yyerror_and_yylex. Not supported -%>
63
+ <%-# b4_declare_yyparse -%>
64
+ int yyparse (<%= output.parse_param %>);
65
+
66
+
67
+ <%-# b4_percent_code_get([[provides]]). %code is not supported -%>
68
+ <%-# b4_cpp_guard_close([b4_spec_mapped_header_file]) -%>
69
+ <%- if output.spec_mapped_header_file -%>
70
+ #endif /* !<%= output.b4_cpp_guard__b4_spec_mapped_header_file %> */
71
+ <%- end -%>
@@ -101,79 +101,13 @@
101
101
  # endif
102
102
 
103
103
  <%# b4_header_include_if -%>
104
+ <%- if output.include_header -%>
105
+ #include "<%= output.include_header %>"
106
+ <%- else -%>
104
107
  /* Use api.header.include to #include this header
105
108
  instead of duplicating it here. */
106
- <%# b4_shared_declarations -%>
107
- <%-# b4_cpp_guard_open([b4_spec_mapped_header_file]) -%>
108
- <%- if output.spec_mapped_header_file -%>
109
- #ifndef <%= output.b4_cpp_guard__b4_spec_mapped_header_file %>
110
- # define <%= output.b4_cpp_guard__b4_spec_mapped_header_file %>
111
- <%- end -%>
112
- <%-# b4_declare_yydebug & b4_YYDEBUG_define -%>
113
- /* Debug traces. */
114
- #ifndef YYDEBUG
115
- # define YYDEBUG 0
116
- #endif
117
- #if YYDEBUG && !defined(yydebug)
118
- extern int yydebug;
119
- #endif
120
- <%-# b4_percent_code_get([[requires]]). %code is not supported -%>
121
-
122
- <%-# b4_token_enums_defines -%>
123
- /* Token kinds. */
124
- #ifndef YYTOKENTYPE
125
- # define YYTOKENTYPE
126
- enum yytokentype
127
- {
128
- <%= output.token_enums -%>
129
- };
130
- typedef enum yytokentype yytoken_kind_t;
131
- #endif
132
-
133
- <%-# b4_declare_yylstype -%>
134
- <%-# b4_value_type_define -%>
135
- /* Value type. */
136
- #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
137
- union YYSTYPE
138
- {
139
- #line <%= output.grammar.union.lineno %> "<%= output.grammar_file_path %>"
140
- <%= output.grammar.union.braces_less_code %>
141
- #line [@oline@] [@ofile@]
142
-
143
- };
144
- typedef union YYSTYPE YYSTYPE;
145
- # define YYSTYPE_IS_TRIVIAL 1
146
- # define YYSTYPE_IS_DECLARED 1
147
- #endif
148
-
149
- <%-# b4_location_type_define -%>
150
- /* Location type. */
151
- #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
152
- typedef struct YYLTYPE YYLTYPE;
153
- struct YYLTYPE
154
- {
155
- int first_line;
156
- int first_column;
157
- int last_line;
158
- int last_column;
159
- };
160
- # define YYLTYPE_IS_DECLARED 1
161
- # define YYLTYPE_IS_TRIVIAL 1
162
- #endif
163
-
164
-
165
-
166
-
167
- <%-# b4_declare_yyerror_and_yylex. Not supported -%>
168
- <%-# b4_declare_yyparse -%>
169
- int yyparse (<%= output.parse_param %>);
170
-
171
-
172
- <%-# b4_percent_code_get([[provides]]). %code is not supported -%>
173
- <%-# b4_cpp_guard_close([b4_spec_mapped_header_file]) -%>
174
- <%- if output.spec_mapped_header_file -%>
175
- #endif /* !<%= output.b4_cpp_guard__b4_spec_mapped_header_file %> */
176
- <%- end -%>
109
+ <%= output.render_partial("bison/_yacc.h") %>
110
+ <%- end -%>
177
111
  <%# b4_declare_symbol_enum -%>
178
112
  /* Symbol kind. */
179
113
  enum yysymbol_kind_t
@@ -2114,3 +2048,4 @@ yyreturnlab:
2114
2048
  #line <%= output.aux.epilogue_first_lineno - 1 %> "<%= output.grammar_file_path %>"
2115
2049
 
2116
2050
  <%= output.aux.epilogue -%>
2051
+