lrama 0.5.6 → 0.5.8

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.6".freeze
2
+ VERSION = "0.5.8".freeze
3
3
  end
data/parser.y ADDED
@@ -0,0 +1,422 @@
1
+ class Lrama::Parser
2
+ token C_DECLARATION CHARACTER IDENT_COLON IDENTIFIER INTEGER STRING TAG
3
+ rule
4
+ input: prologue_declarations bison_declarations "%%" grammar epilogue_opt
5
+
6
+ prologue_declarations: # empty
7
+ | prologue_declarations prologue_declaration
8
+
9
+ prologue_declaration: "%{"
10
+ {
11
+ @lexer.status = :c_declaration
12
+ @lexer.end_symbol = '%}'
13
+ @grammar.prologue_first_lineno = @lexer.line
14
+ }
15
+ C_DECLARATION
16
+ {
17
+ @lexer.status = :initial
18
+ @lexer.end_symbol = nil
19
+ }
20
+ "%}"
21
+ {
22
+ @grammar.prologue = val[2].s_value
23
+ }
24
+ | "%require" STRING
25
+
26
+ bison_declarations: /* empty */ { result = "" }
27
+ | bison_declarations bison_declaration
28
+
29
+ bison_declaration: grammar_declaration
30
+ | "%expect" INTEGER { @grammar.expect = val[1] }
31
+ | "%define" variable value
32
+ | "%require" STRING
33
+ | "%param" params
34
+ | "%lex-param" params
35
+ {
36
+ val[1].each {|token|
37
+ token.references = []
38
+ @grammar.lex_param = @grammar.build_code(:lex_param, token).token_code.s_value
39
+ }
40
+ }
41
+ | "%parse-param" params
42
+ {
43
+ val[1].each {|token|
44
+ token.references = []
45
+ @grammar.parse_param = @grammar.build_code(:parse_param, token).token_code.s_value
46
+ }
47
+ }
48
+ | "%initial-action" "{"
49
+ {
50
+ @lexer.status = :c_declaration
51
+ @lexer.end_symbol = '}'
52
+ }
53
+ C_DECLARATION
54
+ {
55
+ @lexer.status = :initial
56
+ @lexer.end_symbol = nil
57
+ }
58
+ "}"
59
+ {
60
+ @grammar.initial_action = @grammar.build_code(:initial_action, val[3])
61
+ }
62
+ | ";"
63
+
64
+ grammar_declaration: "%union" "{"
65
+ {
66
+ @lexer.status = :c_declaration
67
+ @lexer.end_symbol = '}'
68
+ }
69
+ C_DECLARATION
70
+ {
71
+ @lexer.status = :initial
72
+ @lexer.end_symbol = nil
73
+ }
74
+ "}"
75
+ {
76
+ @grammar.set_union(@grammar.build_code(:union, val[3]), val[3].line)
77
+ }
78
+ | symbol_declaration
79
+ | "%destructor" "{"
80
+ {
81
+ @lexer.status = :c_declaration
82
+ @lexer.end_symbol = '}'
83
+ }
84
+ C_DECLARATION
85
+ {
86
+ @lexer.status = :initial
87
+ @lexer.end_symbol = nil
88
+ }
89
+ "}" generic_symlist
90
+ | "%printer" "{"
91
+ {
92
+ @lexer.status = :c_declaration
93
+ @lexer.end_symbol = '}'
94
+ }
95
+ C_DECLARATION
96
+ {
97
+ @lexer.status = :initial
98
+ @lexer.end_symbol = nil
99
+ }
100
+ "}" generic_symlist
101
+ {
102
+ @grammar.add_printer(ident_or_tags: val[6], code: @grammar.build_code(:printer, val[3]), lineno: val[3].line)
103
+ }
104
+ | "%error-token" "{"
105
+ {
106
+ @lexer.status = :c_declaration
107
+ @lexer.end_symbol = '}'
108
+ }
109
+ C_DECLARATION
110
+ {
111
+ @lexer.status = :initial
112
+ @lexer.end_symbol = nil
113
+ }
114
+ "}" generic_symlist
115
+ {
116
+ @grammar.add_error_token(ident_or_tags: val[6], code: @grammar.build_code(:error_token, val[3]), lineno: val[3].line)
117
+ }
118
+
119
+ symbol_declaration: "%token" token_declarations
120
+ | "%type" symbol_declarations
121
+ {
122
+ val[1].each {|hash|
123
+ hash[:tokens].each {|id|
124
+ @grammar.add_type(id: id, tag: hash[:tag])
125
+ }
126
+ }
127
+ }
128
+ | "%left" token_declarations_for_precedence
129
+ {
130
+ val[1].each {|hash|
131
+ hash[:tokens].each {|id|
132
+ sym = @grammar.add_term(id: id)
133
+ @grammar.add_left(sym, @precedence_number)
134
+ }
135
+ }
136
+ @precedence_number += 1
137
+ }
138
+ | "%right" token_declarations_for_precedence
139
+ {
140
+ val[1].each {|hash|
141
+ hash[:tokens].each {|id|
142
+ sym = @grammar.add_term(id: id)
143
+ @grammar.add_right(sym, @precedence_number)
144
+ }
145
+ }
146
+ @precedence_number += 1
147
+ }
148
+ | "%precedence" token_declarations_for_precedence
149
+ {
150
+ val[1].each {|hash|
151
+ hash[:tokens].each {|id|
152
+ sym = @grammar.add_term(id: id)
153
+ @grammar.add_precedence(sym, @precedence_number)
154
+ }
155
+ }
156
+ @precedence_number += 1
157
+ }
158
+ | "%nonassoc" token_declarations_for_precedence
159
+ {
160
+ val[1].each {|hash|
161
+ hash[:tokens].each {|id|
162
+ sym = @grammar.add_term(id: id)
163
+ @grammar.add_nonassoc(sym, @precedence_number)
164
+ }
165
+ }
166
+ @precedence_number += 1
167
+ }
168
+
169
+ token_declarations: token_declaration_list
170
+ {
171
+ val[0].each {|token_declaration|
172
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: nil, replace: true)
173
+ }
174
+ }
175
+ | TAG token_declaration_list
176
+ {
177
+ val[1].each {|token_declaration|
178
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[0], replace: true)
179
+ }
180
+ }
181
+ | token_declarations TAG token_declaration_list
182
+ {
183
+ val[2].each {|token_declaration|
184
+ @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[1], replace: true)
185
+ }
186
+ }
187
+
188
+ token_declaration_list: token_declaration { result = [val[0]] }
189
+ | token_declaration_list token_declaration { result = val[0].append(val[1]) }
190
+
191
+ token_declaration: id int_opt alias { result = val }
192
+
193
+ int_opt: # empty
194
+ | INTEGER
195
+
196
+ alias: # empty
197
+ | STRING # TODO: change this to string_as_id
198
+
199
+ symbol_declarations: symbol_declaration_list
200
+ {
201
+ result = [{tag: nil, tokens: val[0]}]
202
+ }
203
+ | TAG symbol_declaration_list
204
+ {
205
+ result = [{tag: val[0], tokens: val[1]}]
206
+ }
207
+ | symbol_declarations TAG symbol_declaration_list
208
+ {
209
+ result = val[0].append({tag: val[1], tokens: val[2]})
210
+ }
211
+
212
+ symbol_declaration_list: symbol { result = [val[0]] }
213
+ | symbol_declaration_list symbol { result = val[0].append(val[1]) }
214
+
215
+ symbol: id
216
+ | string_as_id
217
+
218
+ params: params "{"
219
+ {
220
+ @lexer.status = :c_declaration
221
+ @lexer.end_symbol = '}'
222
+ }
223
+ C_DECLARATION
224
+ {
225
+ @lexer.status = :initial
226
+ @lexer.end_symbol = nil
227
+ }
228
+ "}"
229
+ {
230
+ result = val[0].append(val[3])
231
+ }
232
+ | "{"
233
+ {
234
+ @lexer.status = :c_declaration
235
+ @lexer.end_symbol = '}'
236
+ }
237
+ C_DECLARATION
238
+ {
239
+ @lexer.status = :initial
240
+ @lexer.end_symbol = nil
241
+ }
242
+ "}"
243
+ {
244
+ result = [val[2]]
245
+ }
246
+
247
+ token_declarations_for_precedence: token_declaration_list_for_precedence
248
+ {
249
+ result = [{tag: nil, tokens: val[0]}]
250
+ }
251
+ | TAG token_declaration_list_for_precedence
252
+ {
253
+ result = [{tag: val[0], tokens: val[1]}]
254
+ }
255
+ | token_declarations_for_precedence token_declaration_list_for_precedence
256
+ {
257
+ result = val[0].append({tag: nil, tokens: val[1]})
258
+ }
259
+
260
+ token_declaration_list_for_precedence: token_declaration_for_precedence { result = [val[0]] }
261
+ | token_declaration_list_for_precedence token_declaration_for_precedence { result = val[0].append(val[1]) }
262
+
263
+ token_declaration_for_precedence: id
264
+
265
+ id: IDENTIFIER { raise "Ident after %prec" if @prec_seen }
266
+ | CHARACTER { raise "Char after %prec" if @prec_seen }
267
+
268
+ grammar: rules_or_grammar_declaration
269
+ | grammar rules_or_grammar_declaration
270
+
271
+ rules_or_grammar_declaration: rules
272
+ | grammar_declaration ";"
273
+
274
+ rules: id_colon named_ref_opt ":" rhs_list
275
+ {
276
+ lhs = val[0]
277
+ lhs.alias = val[1]
278
+ val[3].each {|hash|
279
+ @grammar.add_rule(lhs: lhs, rhs: hash[:rhs], lineno: hash[:lineno])
280
+ }
281
+ }
282
+
283
+ rhs_list: rhs
284
+ {
285
+ result = [{rhs: val[0], lineno: val[0].first&.line || @lexer.line - 1}]
286
+ }
287
+ | rhs_list "|" rhs
288
+ {
289
+ result = val[0].append({rhs: val[2], lineno: val[2].first&.line || @lexer.line - 1})
290
+ }
291
+ | rhs_list ";"
292
+
293
+ rhs: /* empty */
294
+ {
295
+ result = []
296
+ @prec_seen = false
297
+ @code_after_prec = false
298
+ }
299
+ | rhs symbol named_ref_opt
300
+ {
301
+ token = val[1]
302
+ token.alias = val[2]
303
+ result = val[0].append(token)
304
+ }
305
+ | rhs "{"
306
+ {
307
+ if @prec_seen
308
+ raise "Multiple User_code after %prec" if @code_after_prec
309
+ @code_after_prec = true
310
+ end
311
+ @lexer.status = :c_declaration
312
+ @lexer.end_symbol = '}'
313
+ }
314
+ C_DECLARATION
315
+ {
316
+ @lexer.status = :initial
317
+ @lexer.end_symbol = nil
318
+ }
319
+ "}" named_ref_opt
320
+ {
321
+ token = val[3]
322
+ token.alias = val[6]
323
+ result = val[0].append(token)
324
+ }
325
+ | "{"
326
+ {
327
+ if @prec_seen
328
+ raise "Multiple User_code after %prec" if @code_after_prec
329
+ @code_after_prec = true
330
+ end
331
+ @lexer.status = :c_declaration
332
+ @lexer.end_symbol = '}'
333
+ }
334
+ C_DECLARATION
335
+ {
336
+ @lexer.status = :initial
337
+ @lexer.end_symbol = nil
338
+ }
339
+ "}" named_ref_opt
340
+ {
341
+ token = val[2]
342
+ token.alias = val[5]
343
+ result = [token]
344
+ }
345
+ | rhs "%prec" symbol
346
+ {
347
+ sym = @grammar.find_symbol_by_id!(val[2])
348
+ result = val[0].append(sym)
349
+ @prec_seen = true
350
+ }
351
+
352
+ named_ref_opt: # empty
353
+ | '[' IDENTIFIER ']' { result = val[1].s_value }
354
+
355
+ id_colon: IDENT_COLON
356
+
357
+ epilogue_opt: # empty
358
+ | "%%"
359
+ {
360
+ @lexer.status = :c_declaration
361
+ @lexer.end_symbol = '\Z'
362
+ @grammar.epilogue_first_lineno = @lexer.line + 1
363
+ }
364
+ C_DECLARATION
365
+ {
366
+ @lexer.status = :initial
367
+ @lexer.end_symbol = nil
368
+ @grammar.epilogue = val[2].s_value
369
+ }
370
+
371
+ variable: id
372
+
373
+ value: # empty
374
+ | IDENTIFIER
375
+ | STRING
376
+ | "{...}"
377
+
378
+ generic_symlist: generic_symlist_item { result = [val[0]] }
379
+ | generic_symlist generic_symlist_item { result = val[0].append(val[1]) }
380
+
381
+ generic_symlist_item: symbol
382
+ | TAG
383
+
384
+ string_as_id: STRING { result = Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Ident, s_value: val[0]) }
385
+ end
386
+
387
+ ---- inner
388
+
389
+ include Lrama::Report::Duration
390
+
391
+ def initialize(text, path)
392
+ @text = text
393
+ @path = path
394
+ end
395
+
396
+ def parse
397
+ report_duration(:parse) do
398
+ @lexer = Lrama::Lexer.new(@text)
399
+ @grammar = Lrama::Grammar.new
400
+ @precedence_number = 0
401
+ do_parse
402
+ @grammar.extract_references
403
+ @grammar.prepare
404
+ @grammar.compute_nullable
405
+ @grammar.compute_first_set
406
+ @grammar.validate!
407
+ @grammar
408
+ end
409
+ end
410
+
411
+ def next_token
412
+ @lexer.next_token
413
+ end
414
+
415
+ def on_error(error_token_id, error_value, value_stack)
416
+ source = @text.split("\n")[error_value.line - 1]
417
+ raise ParseError, <<~ERROR
418
+ #{@path}:#{@lexer.line}:#{@lexer.column}: parse error on value #{error_value.inspect} (#{token_to_str(error_token_id) || '?'})
419
+ #{source}
420
+ #{' ' * @lexer.column}^
421
+ ERROR
422
+ 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
+