lrama 0.5.6 → 0.5.7

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.7".freeze
3
3
  end
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
+