rubex 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -0
  4. data/CONTRIBUTING.md +101 -0
  5. data/HISTORY.md +3 -0
  6. data/README.md +112 -297
  7. data/REFERENCE.md +753 -0
  8. data/Rakefile +4 -1
  9. data/TUTORIAL.md +234 -0
  10. data/bin/rubex +1 -1
  11. data/docs/_config.yml +1 -0
  12. data/docs/index.html +1 -0
  13. data/examples/c_struct_interface/c_struct_interface.rb +6 -0
  14. data/examples/c_struct_interface/c_struct_interface.rubex +47 -0
  15. data/examples/linked_list/linked_list.rubex +39 -0
  16. data/examples/linked_list/rb_linked_list.rb +8 -0
  17. data/examples/rcsv wrapper/rcsv/README.md +1 -0
  18. data/examples/rcsv wrapper/rcsv/Rakefile +7 -0
  19. data/examples/rcsv wrapper/rcsv/ext/rcsv/extconf.rb +3 -0
  20. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.c +302 -0
  21. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.rubex +124 -0
  22. data/examples/rcsv wrapper/rcsv/lib/rcsv.rb +8 -0
  23. data/examples/rcsv wrapper/rcsv/lib/rcsv.so +0 -0
  24. data/examples/rcsv wrapper/rcsv/lib/rcsv/version.rb +1 -0
  25. data/examples/rcsv wrapper/rcsv/rcsv.gemspec +27 -0
  26. data/examples/rcsv wrapper/rcsv/spec/rcsv.csv +5 -0
  27. data/examples/rcsv wrapper/rcsv/spec/rcsv_spec.rb +17 -0
  28. data/examples/rcsv wrapper/rcsv/spec/spec_helper.rb +6 -0
  29. data/{spec/fixtures/basic_ruby_method/Makefile → examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/Makefile } +20 -20
  30. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.o +0 -0
  31. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.so +0 -0
  32. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/stage/lib/rcsv.so +0 -0
  33. data/lib/rubex.rb +6 -50
  34. data/lib/rubex/ast.rb +1 -3
  35. data/lib/rubex/ast/expression.rb +1257 -8
  36. data/lib/rubex/ast/node.rb +226 -28
  37. data/lib/rubex/ast/statement.rb +1162 -35
  38. data/lib/rubex/ast/top_statement.rb +815 -0
  39. data/lib/rubex/code_writer.rb +103 -26
  40. data/lib/rubex/compiler.rb +72 -0
  41. data/lib/rubex/compiler_config.rb +19 -0
  42. data/lib/rubex/constants.rb +145 -8
  43. data/lib/rubex/data_type.rb +667 -4
  44. data/lib/rubex/error.rb +15 -0
  45. data/lib/rubex/helpers.rb +154 -0
  46. data/lib/rubex/lexer.rex +186 -22
  47. data/lib/rubex/lexer.rex.rb +261 -35
  48. data/lib/rubex/parser.racc +876 -28
  49. data/lib/rubex/parser.racc.rb +2845 -90
  50. data/lib/rubex/rake_task.rb +34 -0
  51. data/lib/rubex/symbol_table/entry.rb +17 -3
  52. data/lib/rubex/symbol_table/scope.rb +298 -25
  53. data/lib/rubex/version.rb +1 -1
  54. data/rubex.gemspec +11 -3
  55. data/spec/basic_ruby_method_spec.rb +15 -21
  56. data/spec/binding_ptr_args_spec.rb +33 -0
  57. data/spec/bitwise_operators_spec.rb +40 -0
  58. data/spec/blocks_spec.rb +35 -0
  59. data/spec/c_bindings_spec.rb +36 -0
  60. data/spec/c_constants_spec.rb +33 -0
  61. data/spec/c_function_ptrs_spec.rb +38 -0
  62. data/spec/c_functions_spec.rb +35 -0
  63. data/spec/c_struct_interface_spec.rb +38 -0
  64. data/spec/call_by_reference_spec.rb +33 -0
  65. data/spec/class_methods_spec.rb +33 -0
  66. data/spec/class_spec.rb +40 -0
  67. data/spec/comments_spec.rb +33 -0
  68. data/spec/default_args_spec.rb +37 -0
  69. data/spec/error_handling_spec.rb +42 -0
  70. data/spec/examples_spec.rb +52 -0
  71. data/spec/expressions_spec.rb +33 -0
  72. data/spec/fixtures/basic_ruby_method/basic_ruby_method.rubex +2 -0
  73. data/spec/fixtures/binding_ptr_args/binding_ptr_args.rubex +30 -0
  74. data/spec/fixtures/bitwise_operators/bitwise_operators.rubex +40 -0
  75. data/spec/fixtures/blocks/blocks.rubex +11 -0
  76. data/spec/fixtures/c_bindings/c_bindings.rubex +58 -0
  77. data/spec/fixtures/c_constants/c_constants.rubex +7 -0
  78. data/spec/fixtures/c_function_ptrs/c_function_ptrs.rubex +52 -0
  79. data/spec/fixtures/c_functions/c_functions.rubex +25 -0
  80. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +34 -0
  81. data/spec/fixtures/call_by_reference/call_by_reference.rubex +30 -0
  82. data/spec/fixtures/class/class.rubex +20 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +12 -0
  84. data/spec/fixtures/comments/comments.rubex +9 -0
  85. data/spec/fixtures/default_args/default_args.rubex +11 -0
  86. data/spec/fixtures/error_handling/error_handling.rubex +54 -0
  87. data/spec/fixtures/examples/array_to_hash.rubex +14 -0
  88. data/spec/fixtures/examples/rcsv.csv +5 -0
  89. data/spec/fixtures/examples/rcsv.rubex +329 -0
  90. data/spec/fixtures/expressions/expressions.rubex +10 -0
  91. data/spec/fixtures/if_else/if_else.rubex +77 -0
  92. data/spec/fixtures/implicit_lib_include/implicit_lib_include.rubex +15 -0
  93. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +17 -0
  94. data/spec/fixtures/loops/loops.rubex +33 -0
  95. data/spec/fixtures/recursion/recursion.rubex +9 -0
  96. data/spec/fixtures/ruby_constant_method_calls/ruby_constant_method_calls.rubex +17 -0
  97. data/spec/fixtures/ruby_operators/ruby_operators.rubex +29 -0
  98. data/spec/fixtures/ruby_raise/ruby_raise.rubex +13 -0
  99. data/spec/fixtures/ruby_strings/ruby_strings.rubex +19 -0
  100. data/spec/fixtures/ruby_strings/string_blank_bm.rb +37 -0
  101. data/spec/fixtures/ruby_symbols/ruby_symbols.rubex +12 -0
  102. data/spec/fixtures/ruby_types/ruby_types.rubex +15 -0
  103. data/spec/fixtures/statement_expression/statement_expression.rubex +23 -0
  104. data/spec/fixtures/static_array/static_array.rubex +20 -0
  105. data/spec/fixtures/string_literals/string_literals.rubex +15 -0
  106. data/spec/fixtures/struct/struct.rubex +82 -0
  107. data/spec/fixtures/typecasting/typecasting.rubex +23 -0
  108. data/spec/fixtures/var_declarations/var_declarations.rubex +39 -0
  109. data/spec/if_else_spec.rb +39 -0
  110. data/spec/implicit_lib_include_spec.rb +33 -0
  111. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +39 -0
  112. data/spec/loops_spec.rb +34 -0
  113. data/spec/recursion_spec.rb +35 -0
  114. data/spec/ruby_constant_method_calls_spec.rb +35 -0
  115. data/spec/ruby_operators_spec.rb +40 -0
  116. data/spec/ruby_raise_spec.rb +35 -0
  117. data/spec/ruby_strings_spec.rb +33 -0
  118. data/spec/ruby_symbols_spec.rb +37 -0
  119. data/spec/ruby_types_spec.rb +35 -0
  120. data/spec/spec_helper.rb +54 -1
  121. data/spec/statement_expression_spec.rb +34 -0
  122. data/spec/static_array_spec.rb +33 -0
  123. data/spec/string_literals_spec.rb +34 -0
  124. data/spec/struct_spec.rb +36 -0
  125. data/spec/typecasting_spec.rb +38 -0
  126. data/spec/var_declarions_spec.rb +35 -0
  127. metadata +255 -29
  128. data/lib/rubex/ast/argument_list.rb +0 -20
  129. data/lib/rubex/ast/c_base_type.rb +0 -11
  130. data/lib/rubex/ast/ruby_method_def.rb +0 -84
  131. data/spec/fixtures/basic_ruby_method/basic.rb +0 -3
  132. data/spec/fixtures/basic_ruby_method/basic_ruby_method.c +0 -16
  133. data/spec/fixtures/basic_ruby_method/basic_ruby_method.o +0 -0
  134. data/spec/fixtures/basic_ruby_method/basic_ruby_method.so +0 -0
  135. data/spec/fixtures/basic_ruby_method/extconf.rb +0 -3
@@ -1,53 +1,724 @@
1
1
  class Rubex::Parser
2
- token
3
- kDEF kEND kRETURN kDTYPE_I32 tLPAREN tRPAREN tIDENTIFIER tPLUS tNL tCOMMA
2
+ token
3
+ kDEF kEND kRETURN kPRINT kIF kELSIF kELSE kTHEN kSTATIC_ARRAY kFOR
4
+ kDOT_EACH kDO kTRUE kFALSE kNIL kSTRUCT kUNION kALIAS kLIB
5
+ kCFUNC kSELF kNULL kFWD kATTACH kRAISE kBREAK kBLOCK_GIVEN kYIELD
6
+ kBEGIN kRESCUE kENSURE kWHILE kCLASS kDATA_VAR
7
+
8
+ kDTYPE_UINT kDTYPE_LINT kDTYPE_LLINT kDTYPE_CHAR kDTYPE_I8 kDTYPE_I16
9
+ kDTYPE_I32 kDTYPE_I64 kDTYPE_UI8 kDTYPE_UI16 kDTYPE_UI32 kDTYPE_UI64
10
+ kDTYPE_INT kDTYPE_F32 kDTYPE_F64 kDTYPE_LF64 kDTYPE_ROBJ kDTYPE_ULINT
11
+ kDTYPE_ULLINT kDTYPE_VOID kDTYPE_SIZE_T kDTYPE_RB_STR kDTYPE_UCHAR kDTYPE_BOOL
12
+ tCUSTOM_DTYPE kDTYPE_RB_ARR kDTYPE_RB_HSH
13
+
14
+ tLPAREN tRPAREN tLSQUARE tRSQUARE tIDENTIFIER tNL tCOMMA tSQUOTE tSCOLON
15
+ EOF tDOT tQMARK tSYMBOL tLBRACE tRBRACE tCOLON
16
+
17
+ tPLUS tMINUS tSTAR tDIVIDE tEXPO tMODULUS tASSIGN tEQ tLT tLTEQ tGT
18
+ tGTEQ tANDOP tOROP tBANG tOP_ASSIGN tSTRING kSIZEOF
19
+
20
+ tBIT_AND tBIT_OR tBIT_XOR tBIT_LSHIFT tBIT_RSHIFT tBIT_NOT
21
+
22
+ tINTEGER tFLOAT tSINGLE_CHAR
4
23
 
5
24
  prechigh
6
- left tEXPO
7
- left tMULTIPLY tDIVIDE tMODULUS
25
+ right tBANG tBIT_NOT
26
+ right ADDRESS_OF
27
+ right tEXPO
28
+ right TYPECAST
29
+ right kSIZEOF
30
+
31
+ right UMINUS
32
+ left tSTAR tDIVIDE tMODULUS
8
33
  left tPLUS tMINUS
34
+ left tBIT_OR tBIT_XOR
35
+ left tBIT_AND
36
+ left tBIT_LSHIFT tBIT_RSHIFT
37
+ left tLT tLTEQ tGT tGTEQ
38
+ nonassoc tEQ tNEQ
39
+ left tANDOP
40
+ left tOROP
9
41
 
10
- right tEQUAL
42
+ right tASSIGN tOP_ASSIGN
11
43
  preclow
12
44
 
13
45
  rule
14
46
 
15
47
  program:
16
- stmts { result = Node.new(val[0]) }
48
+ opt_terms top_compstmts opt_terms {result = Node.new(val[1])}
17
49
 
18
- stmts:
19
- stmts stmt tNL { result = [val[0], val[1]] }
20
- | stmt tNL { result = [val[0]] }
50
+ top_compstmts:
51
+ top_compstmt { result = [val[0]] }
52
+ | top_compstmts terms top_compstmt { result = [*val[0], val[2]] }
53
+
54
+ top_compstmt:
55
+ c_bindings {}
56
+ | top_stmts terms { result = val[0] }
57
+
58
+ top_stmts:
59
+ { result = [] }
60
+ | top_stmt { result = [val[0]] }
61
+ | top_stmts terms top_stmt { result = [*val[0], val[2]] }
62
+
63
+ top_stmt:
64
+ methods {}
65
+ | klass {}
66
+ | attached_klass {}
67
+ | struct_or_union_def {}
68
+
69
+ klass:
70
+ kCLASS tIDENTIFIER opt_inheritance eol top_stmts opt_terms kEND
71
+ {
72
+ raise Rubex::SyntaxError unless val[1][0].match(/[A-Z]/)
73
+ result = TopStatement::Klass.new val[1], val[2], val[4]
74
+ }
75
+
76
+ attached_klass:
77
+ kCLASS tIDENTIFIER kATTACH dtype opt_inheritance eol top_stmts terms kEND
78
+ {
79
+ raise Rubex::SyntaxError unless val[1][0].match(/[A-Z]/)
80
+ result = TopStatement::AttachedKlass.new(val[1], val[3], val[4], val[6],
81
+ location)
82
+ }
83
+
84
+ opt_inheritance:
85
+ { result = nil }
86
+ | tLT tIDENTIFIER { result = val[1] }
87
+
88
+ c_bindings:
89
+ kLIB tSTRING opt_compilation_cmds c_declarations terms kEND
90
+ {
91
+ result = TopStatement::CBindings.new val[1], val[2], val[3], location
92
+ }
93
+
94
+ opt_compilation_cmds:
95
+ { result = [{}] }
96
+ | compilation_cmd { result = [val[0]] }
97
+ | opt_compilation_cmds tCOMMA compilation_cmd { result = [*val[0], val[2]] }
98
+
99
+ compilation_cmd:
100
+ tIDENTIFIER tCOLON tSTRING
101
+ {
102
+ if val[0] == 'link'
103
+ result = { link: val[2] }
104
+ end
105
+ }
106
+
107
+ c_declarations:
108
+ {}
109
+ | c_declaration { result = [val[0]] }
110
+ | c_declarations terms c_declaration { result = [*val[0], val[2]] }
111
+
112
+ c_declaration:
113
+ c_function_declaration_or_var_decl
114
+ | struct_or_union_def
115
+ | alias_stmt
116
+
117
+ c_function_declaration_or_var_decl:
118
+ dtype opt_star tIDENTIFIER opt_c_func_arg_list
119
+ {
120
+ if !val[3].empty? # function decl
121
+ val[3].pop # HACK: because declared external C functions don't have implicit self argument.
122
+ result = Statement::CFunctionDecl.new val[0], val[1], val[2], val[3]
123
+ else # var/macro decl
124
+ result = variable_decl_nodes([{
125
+ dtype: val[0],
126
+ variables: [{
127
+ ptr_level: val[1],
128
+ ident: val[2]
129
+ }]
130
+ }])[0]
131
+ end
132
+ }
133
+
134
+ c_func_args:
135
+ { result = [] }
136
+ | c_func_normal_arg { result = [Expression::ArgDeclaration.new(val[0])] }
137
+ | c_func_args tCOMMA c_func_normal_arg
138
+ {
139
+ result = [*val[0], Expression::ArgDeclaration.new(val[2])]
140
+ }
141
+
142
+ opt_c_func_arg_list:
143
+ { result = Statement::ArgumentList.new([]) }
144
+ | tLPAREN c_func_args tRPAREN
145
+ {
146
+ # self is a compulsory implicit argument for C methods.
147
+ val[1] << Expression::ArgDeclaration.new(
148
+ { dtype: 'object', variables: [ {ident: 'self' }] })
149
+ result = Statement::ArgumentList.new(val[1])
150
+ }
151
+
152
+ struct_or_union_def:
153
+ kSTRUCT tIDENTIFIER eol var_decl_stmts opt_terms kEND
154
+ {
155
+ add_dtype_to_lexer val[1]
156
+ result = Statement::CStructOrUnionDef.new(val[0], val[1], val[3].flatten,
157
+ location)
158
+ }
159
+
160
+ var_decl_stmts:
161
+ { result = [] }
162
+ | var_decl_stmt { result = [*val[0]] }
163
+ | var_decl_stmts terms var_decl_stmt { result = [*val[0], val[2]] }
164
+
165
+ var_decl_stmt:
166
+ dtype var_decls
167
+ {
168
+ result = variable_decl_nodes([{ dtype: val[0], variables: val[1] }])
169
+ }
170
+
171
+ var_decls:
172
+ var_decls tCOMMA normal_decl { result = [*val[0], val[2]] }
173
+ | normal_decl { result = [val[0]] }
21
174
 
22
- stmt:
23
- kDEF fname f_arglist stmts kEND
175
+ alias_stmt:
176
+ kALIAS ident_or_custom_dtype tASSIGN aliased_type
177
+ { # TODO: take hash from aliased_type and turn into nodes.
178
+ add_dtype_to_lexer val[1]
179
+ result = Statement::Alias.new val[1], val[3], location
180
+ }
181
+
182
+ ident_or_custom_dtype:
183
+ tIDENTIFIER | tCUSTOM_DTYPE {}
184
+
185
+ aliased_type:
186
+ dtype opt_star
24
187
  {
25
- result = RubyMethodDef.new(val[1], val[2])
26
- result.add_statements val[3]
188
+ result = {
189
+ dtype: val[0],
190
+ variables: [
191
+ {
192
+ ptr_level: val[1],
193
+ ident: ""
194
+ }
195
+ ]
196
+ }
197
+ }
198
+ | kSTRUCT tIDENTIFIER opt_star
199
+ {
200
+ result = {
201
+ dtype: "#{val[0]}#{val[1]}",
202
+ variables: [
203
+ {
204
+ ptr_level: val[2],
205
+ ident: ""
206
+ }
207
+ ]
208
+ }
209
+ }
210
+ | dtype opt_star tLPAREN opt_star opt_identifier tRPAREN opt_c_func_arg_list
211
+ {
212
+ result = {
213
+ dtype: val[0],
214
+ variables: [
215
+ {
216
+ ptr_level: val[3],
217
+ ident:{
218
+ return_ptr_level: val[1],
219
+ arg_list: val[6],
220
+ name: val[4]
221
+ }
222
+ }
223
+ ]
224
+ }
27
225
  }
28
- | kRETURN expr { result = Statement::Return.new val[1] }
29
- | {}
30
226
 
31
- fname:
32
- tIDENTIFIER {}
227
+ opt_identifier:
228
+ { result = nil }
229
+ | tIDENTIFIER {}
230
+
231
+ methods:
232
+ ruby_method { result = val[0] }
233
+ | c_function { result = val[0] }
234
+
235
+ ruby_method:
236
+ kDEF opt_singleton f_name f_opt_arglist compstmt kEND
237
+ {
238
+ result = TopStatement::RubyMethodDef.new(
239
+ val[2], val[3], val[4], singleton: val[1])
240
+ }
241
+
242
+ c_function:
243
+ kCFUNC dtype opt_star tIDENTIFIER opt_c_func_arg_list eol compstmt kEND
244
+ {
245
+ if val[4].empty? # since last arg of cfunc must be self.
246
+ val[4] = Statement::ArgumentList.new(
247
+ [
248
+ Expression::ArgDeclaration.new(
249
+ { dtype: 'object', variables: [ { ident: 'self' }] }
250
+ )
251
+ ]
252
+ )
253
+ end
254
+ result = TopStatement::CFunctionDef.new(val[1], val[2], val[3],
255
+ val[4], val[6])
256
+ }
257
+
258
+ c_func_normal_arg:
259
+ dtype opt_star
260
+ {
261
+ result = {
262
+ dtype: val[0],
263
+ variables: [
264
+ {
265
+ ptr_level: val[1],
266
+ ident: ""
267
+ }
268
+ ]
269
+ }
270
+ }
271
+ | dtype normal_decl { result = { dtype: val[0] , variables: [val[1]] } }
272
+ | normal_decl { result = { dtype: 'object', variables: [val[0]] } }
273
+
274
+ opt_singleton:
275
+ { result = false }
276
+ | kSELF tDOT { result = true }
277
+
278
+ compstmt:
279
+ stmts opt_terms { result = val[0] }
280
+
281
+ stmts:
282
+ { result = [] }
283
+ | stmt { result = [*val[0]] }
284
+ | stmts terms stmt { result = [*val[0], *val[2]] }
285
+
286
+
287
+ stmt:
288
+ var_decl_or_init { result = variable_decl_nodes val }
289
+ | kRETURN opt_expr { result = Statement::Return.new val[1], location }
290
+ | kPRINT opt_lparen command_arg_list opt_rparen
291
+ { result = Statement::Print.new val[2], location }
292
+ | normal_init
293
+ {
294
+ match = val[0]
295
+ result = Statement::Assign.new match[:name], match[:value], location
296
+ }
297
+ | kIF expr then compstmt if_tail kEND
298
+ {
299
+ result = Statement::IfBlock.new val[1], [*val[3]], val[4], location
300
+ }
301
+ | stmt kIF expr
302
+ {
303
+ set_location
304
+ result = Statement::IfBlock.new val[2], [*val[0]], nil, location
305
+ }
306
+ | kFOR for_expr kDO compstmt kEND
307
+ {
308
+ result = Statement::For.new *val[1], val[3], location
309
+ }
310
+ | kWHILE expr kDO compstmt kEND
311
+ {
312
+ result = Statement::While.new val[1], val[3], location
313
+ }
314
+ | op_assign {}
315
+ | struct_or_union_def
316
+ | forward_declaration
317
+ | alias_stmt
318
+ | expr { result = Statement::Expression.new(val[0], location) }
319
+ | kRAISE opt_lparen command_arg_list opt_rparen
320
+ {
321
+ result = Statement::Raise.new(Statement::ActualArgList.new(val[2]))
322
+ }
323
+ | kBREAK { result = Statement::Break.new(location) }
324
+ | kYIELD opt_lparen command_arg_list opt_rparen
325
+ {
326
+ result = Statement::Yield.new(Statement::ActualArgList.new(val[2]))
327
+ }
328
+ | begin_block
329
+
330
+ begin_block:
331
+ kBEGIN terms compstmt opt_begin_block_tails kEND
332
+ {
333
+ result = Statement::BeginBlock::Begin.new val[2], val[3], location
334
+ }
335
+
336
+ opt_begin_block_tails:
337
+ opt_rescue_blocks opt_else_block opt_ensure_block
338
+ {
339
+ tails = []
340
+ tails.concat(val[0]) if val[0]
341
+ tails << val[1] if val[1]
342
+ tails << val[2] if val[2]
343
+
344
+ result = tails
345
+ }
346
+
347
+ opt_rescue_blocks:
348
+ { result = nil }
349
+ | rescue_block { result = [val[0]] }
350
+ | opt_rescue_blocks rescue_block { result = [*val[0], val[1]] }
351
+
352
+ rescue_block:
353
+ kRESCUE tIDENTIFIER terms compstmt
354
+ {
355
+ err = Expression::Name.new(val[1])
356
+ result = Statement::BeginBlock::Rescue.new err, nil, val[3] || [], location
357
+ }
358
+
359
+ opt_else_block:
360
+ { result = nil }
361
+ | kELSE terms compstmt
362
+ { result = Statement::BeginBlock::Else.new val[2] || [], location }
363
+
364
+ opt_ensure_block:
365
+ { result = nil }
366
+ | kENSURE terms compstmt
367
+ { result = Statement::BeginBlock::Ensure.new val[2] || [], location }
368
+
369
+ forward_declaration:
370
+ kFWD kSTRUCT tIDENTIFIER
371
+ {
372
+ val.flatten!
373
+ add_dtype_to_lexer val[2]
374
+ result = Statement::ForwardDecl.new val[1], val[2], location
375
+ }
376
+
377
+ op_assign:
378
+ atomic_value tOP_ASSIGN expr
379
+ {
380
+ # TODO: error if lvalue is a literal
381
+ result = op_assign val
382
+ }
383
+
384
+ for_expr:
385
+ tLPAREN actual_for_expr tRPAREN { result = val[1] }
386
+ | actual_for_expr
387
+
388
+ actual_for_expr:
389
+ expr_value lt_or_lteq tIDENTIFIER lt_or_lteq expr_value { result = val }
390
+ | expr_value gt_or_gteq tIDENTIFIER gt_or_gteq expr_value { result = val }
391
+
392
+ lt_or_lteq:
393
+ tLT | tLTEQ
394
+
395
+ gt_or_gteq:
396
+ tGT | tGTEQ
397
+
398
+ then:
399
+ kTHEN | eol
400
+
401
+ if_tail:
402
+ {}
403
+ | opt_else {}
404
+ | kELSIF expr then compstmt if_tail
405
+ {
406
+ result = Statement::IfBlock::Elsif.new val[1], [*val[3]], val[4], location
407
+ }
33
408
 
34
- f_arglist:
35
- tLPAREN f_args tRPAREN tNL { result = val[1] }
409
+ opt_else:
410
+ kELSE compstmt { result = Statement::IfBlock::Else.new val[1], location }
411
+
412
+ var_decl_or_init:
413
+ dtype decls_or_inits
414
+ {
415
+ result = {
416
+ dtype: val[0],
417
+ variables: val[1]
418
+ }
419
+ }
420
+
421
+ decls_or_inits:
422
+ decls_or_inits tCOMMA var_init { result = [*val[0], val[2]] }
423
+ | decls_or_inits tCOMMA normal_decl { result = [*val[0], val[2]] }
424
+ | normal_decl { result = [val[0]] }
425
+ | var_init { result = [val[0]] }
426
+
427
+ normal_decl:
428
+ # possible function pointer declaration
429
+ opt_star tLPAREN opt_star actual_normal_decl tRPAREN opt_c_func_arg_list
430
+ {
431
+ result = {}
432
+
433
+ if val[5] # function (pointer) decl
434
+ result[:ptr_level] = val[2]
435
+ result[:ident] = {
436
+ :return_ptr_level => val[0],
437
+ :name => val[3],
438
+ :arg_list => val[5]
439
+ }
440
+ else
441
+ result[:ptr_level] = val[0].join val[2]
442
+ result[:ident] = val[3]
443
+ end
444
+ }
445
+ | opt_star actual_normal_decl opt_c_func_arg_list
446
+ {
447
+ result = {}
448
+
449
+ if !val[2].empty?
450
+ result[:ptr_level] = val[0]
451
+ result[:ident] = {
452
+ :name => val[1],
453
+ :arg_list => val[2]
454
+ }
455
+ else
456
+ result[:ptr_level] = val[0]
457
+ result[:ident] = val[1]
458
+ end
459
+ }
460
+
461
+ actual_normal_decl: tIDENTIFIER | array_ref
462
+
463
+ var_init:
464
+ normal_decl tASSIGN expr
465
+ {
466
+ result = val[0]
467
+ value = val[2]
468
+
469
+ value.c_array = true if value.is_a?(Expression::Literal::ArrayLit)
470
+ result[:value] = value
471
+ }
472
+
473
+ opt_star:
474
+ { result = nil }
475
+ | opt_star tSTAR { result = val.join }
476
+
477
+ array_list:
478
+ { result = [] }
479
+ | expr { result = [*val[0]] }
480
+ | array_list tCOMMA expr { result = [*val[0], val[2]] }
481
+
482
+ normal_init:
483
+ tIDENTIFIER tASSIGN expr
484
+ {
485
+ result = {
486
+ name: Expression::Name.new(val[0]),
487
+ value: val[2]
488
+ }
489
+ }
490
+ | array_ref tASSIGN expr { result = { name: val[0], value: val[2] } }
491
+ | method_or_attr tASSIGN expr
492
+ {
493
+ result = {
494
+ name: Expression::CommandCall.new(val[0][0], val[0][1], []),
495
+ value: val[2]
496
+ }
497
+ }
498
+
499
+ literal:
500
+ tINTEGER { result = Expression::Literal::Int.new val[0] }
501
+ | tFLOAT { result = Expression::Literal::Double.new val[0] }
502
+ | tSINGLE_CHAR { result = Expression::Literal::Char.new val[0] }
503
+ | tSTRING { result = Expression::Literal::StringLit.new val[0] }
504
+ | kTRUE { result = Expression::Literal::True.new 'Qtrue' }
505
+ | kFALSE { result = Expression::Literal::False.new 'Qfalse' }
506
+ | kNIL { result = Expression::Literal::Nil.new 'Qnil' }
507
+ | tSYMBOL { result = Expression::Literal::RubySymbol.new val[0] }
508
+ | kNULL { result = Expression::Literal::CNull.new val[0] }
509
+ | tLSQUARE opt_eols array_list tRSQUARE
510
+ { result = Expression::Literal::ArrayLit.new val[2] }
511
+ | tLBRACE opt_eols hash_data opt_eols tRBRACE
512
+ { result = Expression::Literal::HashLit.new val[2] }
513
+
514
+ hash_data:
515
+ { result = [] }
516
+ | hash_data_k_v { result = [val[0]] }
517
+ | hash_data tCOMMA opt_eols hash_data_k_v { result = [*val[0], val[3]] }
518
+
519
+ hash_data_k_v:
520
+ atomic_value rocket atomic_value { result = [val[0], val[2]] }
521
+
522
+ rocket:
523
+ tASSIGN tGT
524
+
525
+ f_name:
526
+ tIDENTIFIER tQMARK { result = "#{val[0]}#{val[1]}" }
527
+ | tIDENTIFIER tBANG { result = "#{val[0]}#{val[1]}" }
528
+ | tIDENTIFIER { result = val[0] }
529
+ | kNIL tQMARK { result = "#{val[0]}#{val[1]}" }
530
+
531
+ f_opt_arglist:
532
+ { result = Statement::ArgumentList.new([]) }
533
+ | tLPAREN f_args tRPAREN eol { result = Statement::ArgumentList.new val[1] }
36
534
 
37
535
  f_args:
38
- f_args tCOMMA f_normal_arg
536
+ f_normal_arg
39
537
  {
40
- result = ArgumentList.new
41
- result.push val[0]
42
- result.push val[2]
43
- }
44
- | f_normal_arg { }
538
+ result = [Expression::ArgDeclaration.new(val[0])]
539
+ }
540
+ | f_args tCOMMA f_normal_arg
541
+ {
542
+ result = [*val[0], Expression::ArgDeclaration.new(val[2])]
543
+ }
45
544
 
46
545
  f_normal_arg:
47
- kDTYPE_I32 tIDENTIFIER { result = CBaseType.new val[0], val[1] }
546
+ dtype tIDENTIFIER opt_default_value
547
+ {
548
+ result = {
549
+ dtype: val[0],
550
+ variables: [
551
+ {
552
+ ident: val[1],
553
+ value: val[2]
554
+ }
555
+ ]
556
+ }
557
+ }
558
+ | tIDENTIFIER opt_default_value
559
+ {
560
+ result = {
561
+ dtype: 'object',
562
+ variables: [
563
+ {
564
+ ident: val[0],
565
+ value: val[1]
566
+ }
567
+ ]
568
+ }
569
+ }
570
+
571
+ opt_default_value:
572
+ { result = nil }
573
+ | tASSIGN atomic_value { result = val[1] }
48
574
 
49
575
  expr:
50
- tIDENTIFIER tPLUS tIDENTIFIER { result = Expression::Addition.new val[0], val[2] }
576
+ actual_expr {}
577
+ | typecast actual_expr =TYPECAST
578
+ {
579
+ val[1].typecast = val[0]
580
+ result = val[1]
581
+ }
582
+ | expr tANDOP expr { result = binary_op val }
583
+ | expr tOROP expr { result = binary_op val }
584
+
585
+ typecast:
586
+ tLT dtype opt_star tGT { result = Expression::Typecast.new(val[1], val[2]) }
587
+
588
+ actual_expr:
589
+ expr_value {}
590
+ | expr_cmp {}
591
+ | tBANG expr { result = unary_op val }
592
+ | tLPAREN expr tRPAREN { result = val[1] }
593
+
594
+ expr_value:
595
+ expr_value tPLUS expr_value { result = binary_op val }
596
+ | expr_value tMINUS expr_value { result = binary_op val }
597
+ | expr_value tSTAR expr_value { result = binary_op val }
598
+ | expr_value tDIVIDE expr_value { result = binary_op val }
599
+ | expr_value tEXPO expr_value { result = binary_op val }
600
+ | expr_value tMODULUS expr_value { result = binary_op val }
601
+ | expr_value tBIT_AND expr_value { result = binary_op val }
602
+ | expr_value tBIT_OR expr_value { result = binary_op val }
603
+ | expr_value tBIT_XOR expr_value { result = binary_op val }
604
+ | expr_value tBIT_LSHIFT expr_value { result = binary_op val }
605
+ | expr_value tBIT_RSHIFT expr_value { result = binary_op val }
606
+ | tMINUS expr_value =UMINUS { result = unary_op val }
607
+ | tBIT_AND expr_value =ADDRESS_OF{ result = unary_op val }
608
+ | tBIT_NOT expr_value { result = unary_op val }
609
+ | tLPAREN expr_value tRPAREN { result = val[1] }
610
+ | atomic_value {}
611
+
612
+ expr_cmp:
613
+ expr_value tEQ expr_value { result = binary_op val }
614
+ | expr_value tNEQ expr_value { result = binary_op val }
615
+ | expr_value tLT expr_value { result = binary_op val }
616
+ | expr_value tLTEQ expr_value { result = binary_op val }
617
+ | expr_value tGT expr_value { result = binary_op val }
618
+ | expr_value tGTEQ expr_value { result = binary_op val }
619
+ | tLPAREN expr_cmp tRPAREN { result = val[1] }
620
+
621
+ atomic_value:
622
+ array_ref {}
623
+ | literal {}
624
+ | tIDENTIFIER command_opt_args
625
+ {
626
+ args = val[1]
627
+ result =
628
+ if args.empty?
629
+ Expression::Name.new val[0]
630
+ else
631
+ Expression::CommandCall.new nil, val[0], args
632
+ end
633
+ }
634
+ | command_call
635
+ | kSIZEOF tLPAREN dtype opt_star tRPAREN
636
+ {
637
+ result = Expression::SizeOf.new(val[2], val[3])
638
+ }
639
+ | kBLOCK_GIVEN { result = Expression::BlockGiven.new }
640
+ | kDATA_VAR
641
+ {
642
+ result = Expression::ElementRef.new('data',
643
+ Expression::Literal::Int.new('0'))
644
+ }
645
+
646
+ command_call:
647
+ method_or_attr command_opt_args
648
+ {
649
+ result = Expression::CommandCall.new val[0][0], val[0][1], val[1]
650
+ }
651
+
652
+ method_or_attr:
653
+ atomic_value tDOT f_name
654
+ {
655
+ result = [val[0], val[2]]
656
+ }
657
+ | atomic_value tDOT array_ref
658
+ {
659
+ result = [val[0], val[2]]
660
+ }
661
+
662
+ command_opt_args:
663
+ { result = [] }
664
+ | tLPAREN command_arg_list tRPAREN { result = val[1] }
665
+
666
+ command_arg_list:
667
+ { result = [] }
668
+ | expr { result = val }
669
+ | command_arg_list tCOMMA expr { result = [*val[0], val[2]] }
670
+
671
+ array_ref:
672
+ tIDENTIFIER tLSQUARE expr tRSQUARE
673
+ {
674
+ result = Expression::ElementRef.new val[0], val[2]
675
+ }
676
+
677
+ dtype:
678
+ kDTYPE_UINT | kDTYPE_LINT | kDTYPE_LLINT | kDTYPE_CHAR | kDTYPE_I8 |
679
+ kDTYPE_I16 | kDTYPE_I32 | kDTYPE_I64 | kDTYPE_UI8 | kDTYPE_UI16 |
680
+ kDTYPE_UI32 | kDTYPE_UI64 | kDTYPE_INT | kDTYPE_F32 | kDTYPE_F64 |
681
+ kDTYPE_LF64 | kDTYPE_ROBJ | kDTYPE_ULINT | kDTYPE_ULLINT | kDTYPE_VOID |
682
+ kDTYPE_SIZE_T | kDTYPE_RB_STR | kDTYPE_UCHAR | kDTYPE_BOOL | tCUSTOM_DTYPE |
683
+ kDTYPE_RB_ARR | kDTYPE_RB_HSH
684
+ {
685
+ result = val[0]
686
+ }
687
+
688
+ opt_expr:
689
+ { result = nil }
690
+ | expr
691
+
692
+ opt_lparen:
693
+ {}
694
+ | tLPAREN
695
+
696
+ opt_rparen:
697
+ {}
698
+ | tRPAREN
699
+
700
+ opt_terms:
701
+ {}
702
+ | terms {}
703
+
704
+ terms:
705
+ term {}
706
+ | terms term {}
707
+
708
+ term:
709
+ tNL {}
710
+ | tSCOLON
711
+
712
+ opt_eols:
713
+ {}
714
+ | eols
715
+
716
+ eols:
717
+ eol
718
+ | eols eol
719
+
720
+ eol:
721
+ tNL {result = val[0]}
51
722
  end
52
723
 
53
724
  ---- header
@@ -57,11 +728,188 @@ require_relative 'ast.rb'
57
728
  include Rubex::AST
58
729
 
59
730
  ---- inner
731
+
732
+ attr_reader :lineno, :location, :string
733
+
60
734
  def parse file_name
61
735
  @lexer = Rubex::Lexer.new
736
+ @yydebug = true
737
+ @custom_dtypes = {}
738
+ @prev_token = nil
62
739
  @lexer.parse_file file_name
63
740
  end
64
741
 
742
+ def set_location
743
+ @location = @lexer.location
744
+ end
745
+
746
+ def set_string
747
+ @string = @lexer.ss.string
748
+ end
749
+
750
+ def set_lineno
751
+ @lineno = @lexer.lineno
752
+ end
753
+
65
754
  def next_token
66
- @lexer.next_token
755
+ set_location
756
+ set_string
757
+ set_lineno
758
+
759
+ t = @lexer.next_token
760
+ if !t.nil?
761
+ if t[0] == :tIDENTIFIER
762
+ if @custom_dtypes.has_key?(t[1]) &&
763
+ !(@prev_token[0] == :kSTRUCT || @prev_token[0] == :tDOT)
764
+ t = [:tCUSTOM_DTYPE, t[1]]
765
+ else
766
+ t = check_for_primitive_dtype(t)
767
+ t = check_for_keyword(t)
768
+ end
769
+ end
770
+ end
771
+
772
+ @prev_token = t
773
+ t
774
+ end
775
+
776
+ def check_for_keyword token
777
+ match = token[1]
778
+ if match == "def"
779
+ return [:kDEF, match]
780
+ elsif match == "cfunc"
781
+ return [:kCFUNC, match]
782
+ elsif match == "self"
783
+ return [:kSELF, match]
784
+ elsif match == "do"
785
+ return [:kDO, match]
786
+ elsif match == "end"
787
+ return [:kEND, match]
788
+ elsif match == "return"
789
+ return [:kRETURN, match]
790
+ elsif match == "print"
791
+ return [:kPRINT , match]
792
+ elsif match == "if"
793
+ return [:kIF , match]
794
+ elsif match == "elsif"
795
+ return [:kELSIF , match]
796
+ elsif match == "else"
797
+ return [:kELSE , match]
798
+ elsif match == "then"
799
+ return [:kTHEN , match]
800
+ elsif match == "sizeof"
801
+ return [:kSIZEOF, match]
802
+ elsif match == "raise"
803
+ return [:kRAISE, match]
804
+ elsif match == "break"
805
+ return [:kBREAK, match]
806
+ elsif match == "begin"
807
+ return [:kBEGIN, match]
808
+ elsif match == "ensure"
809
+ return [:kENSURE, match]
810
+ elsif match == "rescue"
811
+ return [:kRESCUE, match]
812
+ end
813
+
814
+ return token
815
+ end
816
+
817
+ def check_for_primitive_dtype token
818
+ match = token[1]
819
+ if match == "char"
820
+ return [:kDTYPE_CHAR, match]
821
+ elsif match == "i8"
822
+ return [:kDTYPE_I8, match]
823
+ elsif match == "i16"
824
+ return [:kDTYPE_I16, match]
825
+ elsif match == "i32"
826
+ return [:kDTYPE_I32, match]
827
+ elsif match == "i64"
828
+ return [:kDTYPE_I64, match]
829
+ elsif match == "u8"
830
+ return [:kDTYPE_UI8, match]
831
+ elsif match == "u16"
832
+ return [:kDTYPE_UI16, match]
833
+ elsif match == "u32"
834
+ return [:kDTYPE_UI32, match]
835
+ elsif match == "u64"
836
+ return [:kDTYPE_UI64, match]
837
+ elsif match == "int"
838
+ return [:kDTYPE_INT, match]
839
+ elsif match == "long"
840
+ return [:kDTYPE_LINT, match]
841
+ elsif match == "f32"
842
+ return [:kDTYPE_F32, match]
843
+ elsif match == "float"
844
+ return [:kDTYPE_F32, match]
845
+ elsif match == "f64"
846
+ return [:kDTYPE_F64, match]
847
+ elsif match == "double"
848
+ return [:kDTYPE_F64, match]
849
+ elsif match == "object"
850
+ return[:kDTYPE_ROBJ, match]
851
+ elsif match == "void"
852
+ return[:kDTYPE_VOID, match]
853
+ elsif match == "size_t"
854
+ return [:kDTYPE_SIZE_T, match]
855
+ elsif match == "str"
856
+ return [:kDTYPE_RB_STR, match]
857
+ elsif match == "arr"
858
+ return [:kDTYPE_RB_ARR, match]
859
+ elsif match == "hsh"
860
+ return [:kDTYPE_RB_HSH, match]
861
+ elsif match == "yield"
862
+ return [:kYIELD, match]
863
+ elsif match == "bool"
864
+ return [:kDTYPE_BOOL, match]
865
+ end
866
+
867
+ token
868
+ end
869
+
870
+ def binary_op val
871
+ Expression::Binary.new val[0], val[1], val[2]
872
+ end
873
+
874
+ def unary_op val
875
+ Expression::Unary.new val[0], val[1]
876
+ end
877
+
878
+ # expr, op_assign, expr => expr = expr op expr
879
+ def op_assign val
880
+ Statement::Assign.new(val[0], binary_op([val[0], val[1][0], val[2]]), location)
881
+ end
882
+
883
+ def variable_decl_nodes val
884
+ variables = val[0]
885
+ type = variables[:dtype]
886
+
887
+ result = variables[:variables].map do |var|
888
+ ident = var[:ident]
889
+ ptr_level = var[:ptr_level]
890
+
891
+ statement =
892
+ if ident.is_a?(Hash) # only if function pointer
893
+ dtype = { dtype: type, ident: ident }
894
+ Statement::CPtrDecl.new(dtype, ident[:name], var[:value], ptr_level,
895
+ location)
896
+ else
897
+ if ptr_level
898
+ Statement::CPtrDecl.new(type, var[:ident], var[:value], ptr_level,
899
+ location)
900
+ elsif ident.is_a?(Expression::ElementRef)
901
+ Statement::CArrayDecl.new(type, var[:ident], var[:value], location)
902
+ else
903
+ Statement::VarDecl.new(type, var[:ident], var[:value], location)
904
+ end
905
+ end
906
+
907
+ statement
908
+ end
909
+
910
+ result
911
+ end
912
+
913
+ def add_dtype_to_lexer dtype
914
+ @custom_dtypes[dtype] = true
67
915
  end