rubex 0.0.1 → 0.1

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.
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