lrama 0.5.6 → 0.5.8

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