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
@@ -0,0 +1,15 @@
1
+ module Rubex
2
+ class SymbolNotFoundError < StandardError; end
3
+
4
+ class ArrayLengthMismatchError < StandardError; end
5
+
6
+ class TypeMismatchError < StandardError; end
7
+
8
+ class SyntaxError < StandardError; end
9
+
10
+ class NoMethodError < StandardError; end
11
+
12
+ class TypeError < StandardError; end
13
+
14
+ class LibraryNotFoundError < StandardError; end
15
+ end
@@ -0,0 +1,154 @@
1
+ module Rubex
2
+ module Helpers
3
+ class << self
4
+ def to_lhs_type lhs, rhs
5
+ if lhs.type.object?
6
+ return rhs.to_ruby_object
7
+ elsif !lhs.type.object? && rhs.type.object?
8
+ return rhs.from_ruby_object(lhs)
9
+ else
10
+ return rhs
11
+ end
12
+ end
13
+
14
+ def result_type_for left, right
15
+ begin
16
+ return left.dup if left == right
17
+ return (left < right ? right.dup : left.dup)
18
+ rescue ArgumentError => e
19
+ raise Rubex::TypeError, e.to_s
20
+ end
21
+ end
22
+
23
+ def determine_dtype data, ptr_level
24
+ if ptr_level && ptr_level[-1] == "*"
25
+ ptr_level = ptr_level.dup
26
+ base_type = Rubex::DataType::CPtr.new simple_dtype(data)
27
+ ptr_level.chop!
28
+
29
+ ptr_level.each_char do |star|
30
+ base_type = Rubex::DataType::CPtr.new base_type
31
+ end
32
+
33
+ return base_type
34
+ else
35
+ return simple_dtype(data)
36
+ end
37
+ end
38
+
39
+ def simple_dtype dtype
40
+ if dtype.is_a?(Rubex::DataType::CFunction)
41
+ dtype
42
+ else
43
+ begin
44
+ Rubex::CUSTOM_TYPES[dtype] || Rubex::TYPE_MAPPINGS[dtype].new
45
+ rescue
46
+ raise Rubex::TypeError, "Type #{dtype} not previously declared."
47
+ end
48
+ end
49
+ end
50
+
51
+ def create_arg_arrays arg_list
52
+ arg_list.inject([]) do |array, arg|
53
+ entry = arg.entry
54
+ c_name = entry.type.base_type.c_function? ? "" : entry.c_name
55
+ array << [entry.type.to_s, c_name]
56
+ array
57
+ end
58
+ end
59
+ end
60
+
61
+ module Writers
62
+ def declare_temps code, scope
63
+ scope.temp_entries.each do |var|
64
+ code.declare_variable type: var.type.to_s, c_name: var.c_name
65
+ end
66
+ end
67
+
68
+ def declare_vars code, scope
69
+ scope.var_entries.each do |var|
70
+ if var.type.base_type.c_function?
71
+ code.declare_func_ptr var: var
72
+ else
73
+ code.declare_variable type: var.type.to_s, c_name: var.c_name
74
+ end
75
+ end
76
+ end
77
+
78
+ def declare_carrays code, scope
79
+ scope.carray_entries.select { |s|
80
+ s.type.dimension.is_a? Rubex::AST::Expression::Literal::Base
81
+ }. each do |arr|
82
+ type = arr.type.type.to_s
83
+ c_name = arr.c_name
84
+ dimension = arr.type.dimension.c_code(@scope)
85
+ value = arr.value.map { |a| a.c_code(@scope) } if arr.value
86
+ code.declare_carray(type: type, c_name: c_name, dimension: dimension,
87
+ value: value)
88
+ end
89
+ end
90
+
91
+ def declare_types code, scope
92
+ scope.type_entries.each do |entry|
93
+ # if !entry.extern
94
+ type = entry.type
95
+
96
+ if type.alias_type?
97
+ base = type.old_type
98
+ if base.respond_to?(:base_type) && base.base_type.c_function?
99
+ func = base.base_type
100
+ str = "typedef #{func.type} (#{type.old_type.ptr_level} #{type.new_type})"
101
+ str << "(" + func.arg_list.map { |e| e.type.to_s }.join(',') + ")"
102
+ str << ";"
103
+ code << str
104
+ else
105
+ code << "typedef #{type.old_type} #{type.new_type};"
106
+ end
107
+ elsif type.struct_or_union? && !entry.extern?
108
+ code << sue_header(entry)
109
+ code.block(sue_footer(entry)) do
110
+ declare_vars code, type.scope
111
+ declare_carrays code, type.scope
112
+ declare_ruby_objects code, type.scope
113
+ end
114
+ end
115
+ code.nl
116
+ # end
117
+ end
118
+ end
119
+
120
+ def sue_header entry
121
+ type = entry.type
122
+ str = "#{type.kind} #{type.name}"
123
+ if !entry.extern
124
+ str.prepend "typedef "
125
+ end
126
+
127
+ str
128
+ end
129
+
130
+ def sue_footer entry
131
+ str =
132
+ if entry.extern
133
+ ";"
134
+ else
135
+ " #{entry.type.c_name};"
136
+ end
137
+
138
+ str
139
+ end
140
+
141
+ def declare_ruby_objects code, scope
142
+ scope.ruby_obj_entries.each do |var|
143
+ code.declare_variable type: var.type.to_s, c_name: var.c_name
144
+ end
145
+ end
146
+ end
147
+
148
+ module NodeTypeMethods
149
+ [:expression?, :statement?, :literal?, :ruby_method?].each do |meth|
150
+ define_method(meth) { false }
151
+ end
152
+ end
153
+ end
154
+ end
@@ -1,50 +1,214 @@
1
1
  class Rubex::Lexer
2
+ options
3
+ lineno
2
4
  macros
5
+ # reserved words
6
+
7
+ SELF /self/
3
8
  DEF /def/
9
+ CFUNC /cfunc/
4
10
  RETURN /return/
11
+ PRINT /print/
12
+ IF /if/
13
+ ELSE /else/
14
+ ELSIF /elsif/
15
+ THEN /then/
16
+ STATIC_ARRAY /StaticArray/
17
+ FOR /for/
18
+ WHILE /while/
19
+ DO /do/
20
+ EACH /each/
21
+ TRUE /true/
22
+ FALSE /false/
23
+ NIL /nil/
24
+ STRUCT /struct/
25
+ UNION /union/
26
+ ALIAS /alias/
27
+ LIB /lib/
28
+ CLASS /class/
29
+ NULL /NULL/
30
+ ATTACH /attach/
31
+ BLOCK_GIVEN /block_given\?/
5
32
 
6
- IDENTIFIER /[a-z_][a-zA-Z_0-9]*/
33
+ IDENTIFIER /[a-zA-Z_][a-zA-Z_0-9]*/
7
34
  LPAREN /\(/
8
35
  RPAREN /\)/
36
+ LSQUARE /\[/
37
+ RSQUARE /\]/
38
+ LBRACE /{/
39
+ RBRACE /}/
9
40
  NL /\n/
10
41
  COMMA /,/
42
+ SQUOTE /'/
43
+ DQUOTE /"/
44
+ SCOLON /;/
45
+ COLON /:/
46
+ INTEGER /-?\d+/
47
+ FLOAT /-?\d+\.\d+/
48
+ DOT /\./
49
+ QMARK /\?/
50
+ OCTOTHORP /#/
11
51
 
12
52
  # operators
53
+
13
54
  EXPO /\*\*/
14
- MULTIPLY /\*/
55
+ EXPOASSIGN /\*\*=/
56
+ STAR /\*/
57
+ STARASSIGN /\*=/
15
58
  DIVIDE /\//
59
+ DIVIDEASSIGN /\/=/
16
60
  PLUS /\+/
61
+ PLUSASSIGN /\+=/
17
62
  MINUS /\-/
63
+ MINUSASSIGN /\-=/
18
64
  MODULUS /%/
19
- EQUAL /=/
65
+ MODULUSASSIGN /%=/
66
+ ASSIGN /=/
67
+ NEQ /!=/
68
+ EQ /==/
69
+ LT /</
70
+ LTEQ /<=/
71
+ GT />/
72
+ GTEQ />=/
73
+ ANDOP /&&/
74
+ OROP /\|\|/
75
+ BANG /!/
76
+ BIT_AND /&/
77
+ BIT_AND_ASSIGN /&=/
78
+ BIT_OR /\|/
79
+ BIT_OR_ASSIGN /\|=/
80
+ BIT_XOR /\^/
81
+ BIT_XOR_ASSIGN /\^=/
82
+ BIT_LSHIFT /<</
83
+ BIT_LSHIFT_ASSIGN /<<=/
84
+ BIT_RSHIFT />>/
85
+ BIT_RSHIFT_ASSIGN />>=/
86
+ BIT_NOT /~/
87
+
20
88
  rules
21
- /#{DEF}/ { [:kDEF, text] }
22
- /end/ { [:kEND, text] }
23
- /#{RETURN}/ { [:kRETURN, text] }
24
89
 
25
- /i32/ { [:kDTYPE_I32, text] }
90
+ # literals
91
+
92
+ /'.\'/ { [:tSINGLE_CHAR, text] }
93
+ /#{FLOAT}/ { [:tFLOAT, text] }
94
+ /#{INTEGER}/ { [:tINTEGER, text] }
95
+
96
+ # String literal
97
+
98
+ /#{DQUOTE}/ { @state = :STRING_LITERAL; @string_text = ""; nil }
99
+ :STRING_LITERAL /#{DQUOTE}/ { @state = nil; return [:tSTRING, @string_text] }
100
+ :STRING_LITERAL /[^"\\]/ { @string_text << text; nil }
101
+ :STRING_LITERAL /\\/ { @state = :STRING_LITERAL_BSLASH; @string_text << text; nil }
102
+ :STRING_LITERAL_BSLASH /./ { @state = :STRING_LITERAL; @string_text << text; nil }
103
+
104
+ # Comments
105
+
106
+ /#{OCTOTHORP}/ { @state = :COMMENT; nil }
107
+ :COMMENT /./ { @state = :COMMENT; nil }
108
+ # return a tNL since it is a way for the parser to figure that a line of code has end.
109
+ :COMMENT /\n/ { @state = nil; [:tNL, "\n"] }
110
+
111
+ # Reserved words
112
+
113
+ /#{STATIC_ARRAY}/ { [:kSTATIC_ARRAY, text] }
114
+ /#{FOR}/ { [:kFOR, text] }
115
+ /#{WHILE}/ { [:kWHILE, text] }
116
+ /#{TRUE}/ { [:kTRUE, text] }
117
+ /#{FALSE}/ { [:kFALSE, text] }
118
+ /#{NIL}/ { [:kNIL, text] }
119
+ /#{LIB}/ { [:kLIB, text] }
120
+ /#{CLASS}/ { [:kCLASS, text] }
121
+ /#{NULL}/ { [:kNULL, text] }
122
+ /fwd/ { [:kFWD, text] }
123
+ /#{ATTACH}/ { [:kATTACH, text] }
124
+ /#{BLOCK_GIVEN}/ { [:kBLOCK_GIVEN, text] }
125
+
126
+ # Method hacks
26
127
 
27
- /#{IDENTIFIER}/ { [:tIDENTIFIER, text] }
28
- /#{LPAREN}/ { [:tLPAREN, text] }
29
- /#{RPAREN}/ { [:tRPAREN, text] }
30
- /#{NL}/ { [:tNL, text] }
31
- /#{COMMA}/ { [:tCOMMA, text] }
128
+ /data\$/ { [:kDATA_VAR, text] }
129
+ /#{DOT}#{EACH}/ { [:kDOT_EACH, text] }
130
+
131
+ # Data Types
132
+
133
+ /unsigned long long int/ { [:kDTYPE_ULLINT, text] }
134
+ /unsigned long int/ { [:kDTYPE_ULINT, text] }
135
+ /unsigned int/ { [:kDTYPE_UINT, text] }
136
+ /unsigned char/ { [:kDTYPE_UCHAR, text] }
137
+ /long int/ { [:kDTYPE_LINT, text] }
138
+ /long long int/ { [:kDTYPE_LLINT, text] }
139
+ # /long double/ { [:kDTYPE_LF64, text] }
140
+ # /long f64/ { [:kDTYPE_LF64, text] }
141
+
142
+ # Keywords
143
+
144
+ /#{STRUCT}\ / { [:kSTRUCT, text] }
145
+ /#{UNION}\ / { [:kUNION, text] }
146
+ /#{ALIAS}\ / { [:kALIAS, text] }
147
+
148
+ /:#{IDENTIFIER}/ { [:tSYMBOL, text] }
149
+ /#{IDENTIFIER}/ { [:tIDENTIFIER, text] }
150
+ /#{LBRACE}/ { [:tLBRACE, text] }
151
+ /#{RBRACE}/ { [:tRBRACE, text] }
152
+ /#{LPAREN}/ { [:tLPAREN, text] }
153
+ /#{RPAREN}/ { [:tRPAREN, text] }
154
+ /#{LSQUARE}/ { [:tLSQUARE, text] }
155
+ /#{RSQUARE}/ { [:tRSQUARE, text] }
156
+ /#{COMMA}/ { [:tCOMMA, text] }
157
+ /#{SCOLON}/ { [:tSCOLON, text] }
158
+ /#{NL}/ { [:tNL, text] }
159
+ /#{QMARK}/ { [:tQMARK, text]}
160
+ /#{DOT}/ { [:tDOT, text] }
161
+ /#{COLON}/ { [:tCOLON, text] }
32
162
 
33
163
  # operators
34
164
 
35
- /#{PLUS}/ { [:tPLUS, text]}
36
- /#{MINUS}/ { [:tMINUS, text]}
37
- /#{MULTIPLY}/ { [:tMULTIPLY, text]}
38
- /#{DIVIDE}/ { [:tDIVIDE, text]}
39
- /#{EXPO}/ { [:tEXPO, text]}
40
- /#{MODULUS}/ { [:tMODULUS, text]}
41
- /#{EXPO}/ { [:tEXPO, text]}
165
+ /#{PLUSASSIGN}/ { [:tOP_ASSIGN, text]}
166
+ /#{MINUSASSIGN}/ { [:tOP_ASSIGN, text]}
167
+ /#{STARASSIGN}/ { [:tOP_ASSIGN, text]}
168
+ /#{DIVIDEASSIGN}/ { [:tOP_ASSIGN, text]}
169
+ /#{EXPOASSIGN}/ { [:tOP_ASSIGN, text]}
170
+ /#{MODULUSASSIGN}/ { [:tOP_ASSIGN, text]}
171
+ /#{PLUS}/ { [:tPLUS, text]}
172
+ /#{MINUS}/ { [:tMINUS, text]}
173
+ /#{STAR}/ { [:tSTAR, text]}
174
+ /#{DIVIDE}/ { [:tDIVIDE, text]}
175
+ /#{EXPO}/ { [:tEXPO, text]}
176
+ /#{MODULUS}/ { [:tMODULUS, text]}
177
+ /#{EXPO}/ { [:tEXPO, text]}
178
+ /#{EQ}/ { [:tEQ, text] }
179
+ /#{NEQ}/ { [:tNEQ, text] }
180
+ /#{ASSIGN}/ { [:tASSIGN, text] }
181
+ /#{BANG}/ { [:tBANG, text] }
182
+
183
+ /#{ANDOP}/ { [:tANDOP, text] }
184
+ /#{OROP}/ { [:tOROP, text] }
185
+
186
+ /#{BIT_AND_ASSIGN}/ { [:tOP_ASSIGN, text] }
187
+ /#{BIT_OR_ASSIGN}/ { [:tOP_ASSIGN , text] }
188
+ /#{BIT_XOR_ASSIGN}/ { [:tOP_ASSIGN , text] }
189
+ /#{BIT_LSHIFT_ASSIGN}/ { [:tOP_ASSIGN, text] }
190
+ /#{BIT_RSHIFT_ASSIGN}/ { [:tOP_ASSIGN, text] }
191
+ /#{BIT_AND}/ { [:tBIT_AND , text] }
192
+ /#{BIT_OR}/ { [:tBIT_OR , text] }
193
+ /#{BIT_XOR}/ { [:tBIT_XOR , text] }
194
+ /#{BIT_LSHIFT}/ { [:tBIT_LSHIFT , text] }
195
+ /#{BIT_RSHIFT}/ { [:tBIT_RSHIFT , text] }
196
+ /#{BIT_NOT}/ { [:tBIT_NOT, text] }
197
+
198
+ /#{LTEQ}/ { [:tLTEQ, text] }
199
+ /#{LT}/ { [:tLT, text] }
200
+
201
+ /#{GTEQ}/ { [:tGTEQ, text] }
202
+ /#{GT}/ { [:tGT, text] }
42
203
 
43
204
  # whitespace
44
205
 
45
- / / {}
206
+ /^\n\s*$/
207
+ /\s+/
208
+
46
209
  inner
47
210
  def do_parse
48
- # this is a stub since oedipus lex uses this internally.
211
+ self.ss.string = self.ss.string.split("\n").map! { |e| e.rstrip }.join("\n")
212
+ self.ss << "\n"
49
213
  end
50
- end # Rubex::Lexer
214
+ end # Rubex::Lexer
@@ -1,30 +1,94 @@
1
1
  # encoding: UTF-8
2
2
  #--
3
3
  # This file is automatically generated. Do not modify it.
4
- # Generated by: oedipus_lex version 2.4.1.
4
+ # Generated by: oedipus_lex version 2.5.0.
5
5
  # Source: lib/rubex/lexer.rex
6
6
  #++
7
7
 
8
8
  class Rubex::Lexer
9
9
  require 'strscan'
10
10
 
11
- DEF = /def/
12
- RETURN = /return/
13
- IDENTIFIER = /[a-z_][a-zA-Z_0-9]*/
14
- LPAREN = /\(/
15
- RPAREN = /\)/
16
- NL = /\n/
17
- COMMA = /,/
18
- EXPO = /\*\*/
19
- MULTIPLY = /\*/
20
- DIVIDE = /\//
21
- PLUS = /\+/
22
- MINUS = /\-/
23
- MODULUS = /%/
24
- EQUAL = /=/
25
-
26
- class ScanError < StandardError ; end
11
+ SELF = /self/
12
+ DEF = /def/
13
+ CFUNC = /cfunc/
14
+ RETURN = /return/
15
+ PRINT = /print/
16
+ IF = /if/
17
+ ELSE = /else/
18
+ ELSIF = /elsif/
19
+ THEN = /then/
20
+ STATIC_ARRAY = /StaticArray/
21
+ FOR = /for/
22
+ WHILE = /while/
23
+ DO = /do/
24
+ EACH = /each/
25
+ TRUE = /true/
26
+ FALSE = /false/
27
+ NIL = /nil/
28
+ STRUCT = /struct/
29
+ UNION = /union/
30
+ ALIAS = /alias/
31
+ LIB = /lib/
32
+ CLASS = /class/
33
+ NULL = /NULL/
34
+ ATTACH = /attach/
35
+ BLOCK_GIVEN = /block_given\?/
36
+ IDENTIFIER = /[a-zA-Z_][a-zA-Z_0-9]*/
37
+ LPAREN = /\(/
38
+ RPAREN = /\)/
39
+ LSQUARE = /\[/
40
+ RSQUARE = /\]/
41
+ LBRACE = /{/
42
+ RBRACE = /}/
43
+ NL = /\n/
44
+ COMMA = /,/
45
+ SQUOTE = /'/
46
+ DQUOTE = /"/
47
+ SCOLON = /;/
48
+ COLON = /:/
49
+ INTEGER = /-?\d+/
50
+ FLOAT = /-?\d+\.\d+/
51
+ DOT = /\./
52
+ QMARK = /\?/
53
+ OCTOTHORP = /#/
54
+ EXPO = /\*\*/
55
+ EXPOASSIGN = /\*\*=/
56
+ STAR = /\*/
57
+ STARASSIGN = /\*=/
58
+ DIVIDE = /\//
59
+ DIVIDEASSIGN = /\/=/
60
+ PLUS = /\+/
61
+ PLUSASSIGN = /\+=/
62
+ MINUS = /\-/
63
+ MINUSASSIGN = /\-=/
64
+ MODULUS = /%/
65
+ MODULUSASSIGN = /%=/
66
+ ASSIGN = /=/
67
+ NEQ = /!=/
68
+ EQ = /==/
69
+ LT = /</
70
+ LTEQ = /<=/
71
+ GT = />/
72
+ GTEQ = />=/
73
+ ANDOP = /&&/
74
+ OROP = /\|\|/
75
+ BANG = /!/
76
+ BIT_AND = /&/
77
+ BIT_AND_ASSIGN = /&=/
78
+ BIT_OR = /\|/
79
+ BIT_OR_ASSIGN = /\|=/
80
+ BIT_XOR = /\^/
81
+ BIT_XOR_ASSIGN = /\^=/
82
+ BIT_LSHIFT = /<</
83
+ BIT_LSHIFT_ASSIGN = /<<=/
84
+ BIT_RSHIFT = />>/
85
+ BIT_RSHIFT_ASSIGN = />>=/
86
+ BIT_NOT = /~/
27
87
 
88
+ class LexerError < StandardError ; end
89
+ class ScanError < LexerError ; end
90
+
91
+ attr_accessor :lineno
28
92
  attr_accessor :filename
29
93
  attr_accessor :ss
30
94
  attr_accessor :state
@@ -41,13 +105,13 @@ class Rubex::Lexer
41
105
  yield
42
106
  end
43
107
 
44
-
45
108
  def scanner_class
46
109
  StringScanner
47
110
  end unless instance_methods(false).map(&:to_s).include?("scanner_class")
48
111
 
49
112
  def parse str
50
113
  self.ss = scanner_class.new str
114
+ self.lineno = 1
51
115
  self.state ||= nil
52
116
 
53
117
  do_parse
@@ -60,39 +124,125 @@ class Rubex::Lexer
60
124
  end
61
125
  end
62
126
 
127
+ def location
128
+ [
129
+ (filename || "<input>"),
130
+ lineno,
131
+ ].compact.join(":")
132
+ end
133
+
63
134
  def next_token
64
135
 
65
136
  token = nil
66
137
 
67
138
  until ss.eos? or token do
139
+ self.lineno += 1 if ss.peek(1) == "\n"
68
140
  token =
69
141
  case state
70
142
  when nil then
71
143
  case
72
- when text = ss.scan(/#{DEF}/) then
73
- action { [:kDEF, text] }
74
- when text = ss.scan(/end/) then
75
- action { [:kEND, text] }
76
- when text = ss.scan(/#{RETURN}/) then
77
- action { [:kRETURN, text] }
78
- when text = ss.scan(/i32/) then
79
- action { [:kDTYPE_I32, text] }
144
+ when text = ss.scan(/'.\'/) then
145
+ action { [:tSINGLE_CHAR, text] }
146
+ when text = ss.scan(/#{FLOAT}/) then
147
+ action { [:tFLOAT, text] }
148
+ when text = ss.scan(/#{INTEGER}/) then
149
+ action { [:tINTEGER, text] }
150
+ when ss.skip(/#{DQUOTE}/) then
151
+ action { @state = :STRING_LITERAL; @string_text = ""; nil }
152
+ when ss.skip(/#{OCTOTHORP}/) then
153
+ action { @state = :COMMENT; nil }
154
+ when text = ss.scan(/#{STATIC_ARRAY}/) then
155
+ action { [:kSTATIC_ARRAY, text] }
156
+ when text = ss.scan(/#{FOR}/) then
157
+ action { [:kFOR, text] }
158
+ when text = ss.scan(/#{WHILE}/) then
159
+ action { [:kWHILE, text] }
160
+ when text = ss.scan(/#{TRUE}/) then
161
+ action { [:kTRUE, text] }
162
+ when text = ss.scan(/#{FALSE}/) then
163
+ action { [:kFALSE, text] }
164
+ when text = ss.scan(/#{NIL}/) then
165
+ action { [:kNIL, text] }
166
+ when text = ss.scan(/#{LIB}/) then
167
+ action { [:kLIB, text] }
168
+ when text = ss.scan(/#{CLASS}/) then
169
+ action { [:kCLASS, text] }
170
+ when text = ss.scan(/#{NULL}/) then
171
+ action { [:kNULL, text] }
172
+ when text = ss.scan(/fwd/) then
173
+ action { [:kFWD, text] }
174
+ when text = ss.scan(/#{ATTACH}/) then
175
+ action { [:kATTACH, text] }
176
+ when text = ss.scan(/#{BLOCK_GIVEN}/) then
177
+ action { [:kBLOCK_GIVEN, text] }
178
+ when text = ss.scan(/data\$/) then
179
+ action { [:kDATA_VAR, text] }
180
+ when text = ss.scan(/#{DOT}#{EACH}/) then
181
+ action { [:kDOT_EACH, text] }
182
+ when text = ss.scan(/unsigned long long int/) then
183
+ action { [:kDTYPE_ULLINT, text] }
184
+ when text = ss.scan(/unsigned long int/) then
185
+ action { [:kDTYPE_ULINT, text] }
186
+ when text = ss.scan(/unsigned int/) then
187
+ action { [:kDTYPE_UINT, text] }
188
+ when text = ss.scan(/unsigned char/) then
189
+ action { [:kDTYPE_UCHAR, text] }
190
+ when text = ss.scan(/long int/) then
191
+ action { [:kDTYPE_LINT, text] }
192
+ when text = ss.scan(/long long int/) then
193
+ action { [:kDTYPE_LLINT, text] }
194
+ when text = ss.scan(/#{STRUCT}\ /) then
195
+ action { [:kSTRUCT, text] }
196
+ when text = ss.scan(/#{UNION}\ /) then
197
+ action { [:kUNION, text] }
198
+ when text = ss.scan(/#{ALIAS}\ /) then
199
+ action { [:kALIAS, text] }
200
+ when text = ss.scan(/:#{IDENTIFIER}/) then
201
+ action { [:tSYMBOL, text] }
80
202
  when text = ss.scan(/#{IDENTIFIER}/) then
81
203
  action { [:tIDENTIFIER, text] }
204
+ when text = ss.scan(/#{LBRACE}/) then
205
+ action { [:tLBRACE, text] }
206
+ when text = ss.scan(/#{RBRACE}/) then
207
+ action { [:tRBRACE, text] }
82
208
  when text = ss.scan(/#{LPAREN}/) then
83
209
  action { [:tLPAREN, text] }
84
210
  when text = ss.scan(/#{RPAREN}/) then
85
211
  action { [:tRPAREN, text] }
86
- when text = ss.scan(/#{NL}/) then
87
- action { [:tNL, text] }
212
+ when text = ss.scan(/#{LSQUARE}/) then
213
+ action { [:tLSQUARE, text] }
214
+ when text = ss.scan(/#{RSQUARE}/) then
215
+ action { [:tRSQUARE, text] }
88
216
  when text = ss.scan(/#{COMMA}/) then
89
217
  action { [:tCOMMA, text] }
218
+ when text = ss.scan(/#{SCOLON}/) then
219
+ action { [:tSCOLON, text] }
220
+ when text = ss.scan(/#{NL}/) then
221
+ action { [:tNL, text] }
222
+ when text = ss.scan(/#{QMARK}/) then
223
+ action { [:tQMARK, text]}
224
+ when text = ss.scan(/#{DOT}/) then
225
+ action { [:tDOT, text] }
226
+ when text = ss.scan(/#{COLON}/) then
227
+ action { [:tCOLON, text] }
228
+ when text = ss.scan(/#{PLUSASSIGN}/) then
229
+ action { [:tOP_ASSIGN, text]}
230
+ when text = ss.scan(/#{MINUSASSIGN}/) then
231
+ action { [:tOP_ASSIGN, text]}
232
+ when text = ss.scan(/#{STARASSIGN}/) then
233
+ action { [:tOP_ASSIGN, text]}
234
+ when text = ss.scan(/#{DIVIDEASSIGN}/) then
235
+ action { [:tOP_ASSIGN, text]}
236
+ when text = ss.scan(/#{EXPOASSIGN}/) then
237
+ action { [:tOP_ASSIGN, text]}
238
+ when text = ss.scan(/#{MODULUSASSIGN}/) then
239
+ action { [:tOP_ASSIGN, text]}
90
240
  when text = ss.scan(/#{PLUS}/) then
91
241
  action { [:tPLUS, text]}
92
242
  when text = ss.scan(/#{MINUS}/) then
93
243
  action { [:tMINUS, text]}
94
- when text = ss.scan(/#{MULTIPLY}/) then
95
- action { [:tMULTIPLY, text]}
244
+ when text = ss.scan(/#{STAR}/) then
245
+ action { [:tSTAR, text]}
96
246
  when text = ss.scan(/#{DIVIDE}/) then
97
247
  action { [:tDIVIDE, text]}
98
248
  when text = ss.scan(/#{EXPO}/) then
@@ -101,20 +251,94 @@ class Rubex::Lexer
101
251
  action { [:tMODULUS, text]}
102
252
  when text = ss.scan(/#{EXPO}/) then
103
253
  action { [:tEXPO, text]}
104
- when ss.skip(/ /) then
105
- action {}
254
+ when text = ss.scan(/#{EQ}/) then
255
+ action { [:tEQ, text] }
256
+ when text = ss.scan(/#{NEQ}/) then
257
+ action { [:tNEQ, text] }
258
+ when text = ss.scan(/#{ASSIGN}/) then
259
+ action { [:tASSIGN, text] }
260
+ when text = ss.scan(/#{BANG}/) then
261
+ action { [:tBANG, text] }
262
+ when text = ss.scan(/#{ANDOP}/) then
263
+ action { [:tANDOP, text] }
264
+ when text = ss.scan(/#{OROP}/) then
265
+ action { [:tOROP, text] }
266
+ when text = ss.scan(/#{BIT_AND_ASSIGN}/) then
267
+ action { [:tOP_ASSIGN, text] }
268
+ when text = ss.scan(/#{BIT_OR_ASSIGN}/) then
269
+ action { [:tOP_ASSIGN , text] }
270
+ when text = ss.scan(/#{BIT_XOR_ASSIGN}/) then
271
+ action { [:tOP_ASSIGN , text] }
272
+ when text = ss.scan(/#{BIT_LSHIFT_ASSIGN}/) then
273
+ action { [:tOP_ASSIGN, text] }
274
+ when text = ss.scan(/#{BIT_RSHIFT_ASSIGN}/) then
275
+ action { [:tOP_ASSIGN, text] }
276
+ when text = ss.scan(/#{BIT_AND}/) then
277
+ action { [:tBIT_AND , text] }
278
+ when text = ss.scan(/#{BIT_OR}/) then
279
+ action { [:tBIT_OR , text] }
280
+ when text = ss.scan(/#{BIT_XOR}/) then
281
+ action { [:tBIT_XOR , text] }
282
+ when text = ss.scan(/#{BIT_LSHIFT}/) then
283
+ action { [:tBIT_LSHIFT , text] }
284
+ when text = ss.scan(/#{BIT_RSHIFT}/) then
285
+ action { [:tBIT_RSHIFT , text] }
286
+ when text = ss.scan(/#{BIT_NOT}/) then
287
+ action { [:tBIT_NOT, text] }
288
+ when text = ss.scan(/#{LTEQ}/) then
289
+ action { [:tLTEQ, text] }
290
+ when text = ss.scan(/#{LT}/) then
291
+ action { [:tLT, text] }
292
+ when text = ss.scan(/#{GTEQ}/) then
293
+ action { [:tGTEQ, text] }
294
+ when text = ss.scan(/#{GT}/) then
295
+ action { [:tGT, text] }
296
+ when ss.skip(/^\n\s*$/) then
297
+ # do nothing
298
+ when ss.skip(/\s+/) then
299
+ # do nothing
300
+ else
301
+ text = ss.string[ss.pos .. -1]
302
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
303
+ end
304
+ when :STRING_LITERAL then
305
+ case
306
+ when ss.skip(/#{DQUOTE}/) then
307
+ action { @state = nil; return [:tSTRING, @string_text] }
308
+ when text = ss.scan(/[^"\\]/) then
309
+ action { @string_text << text; nil }
310
+ when text = ss.scan(/\\/) then
311
+ action { @state = :STRING_LITERAL_BSLASH; @string_text << text; nil }
312
+ else
313
+ text = ss.string[ss.pos .. -1]
314
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
315
+ end
316
+ when :STRING_LITERAL_BSLASH then
317
+ case
318
+ when text = ss.scan(/./) then
319
+ action { @state = :STRING_LITERAL; @string_text << text; nil }
320
+ else
321
+ text = ss.string[ss.pos .. -1]
322
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
323
+ end
324
+ when :COMMENT then
325
+ case
326
+ when ss.skip(/./) then
327
+ action { @state = :COMMENT; nil }
328
+ when ss.skip(/\n/) then
329
+ action { @state = nil; [:tNL, "\n"] }
106
330
  else
107
331
  text = ss.string[ss.pos .. -1]
108
- raise ScanError, "can not match (#{state.inspect}): '#{text}'"
332
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
109
333
  end
110
334
  else
111
- raise ScanError, "undefined state: '#{state}'"
335
+ raise ScanError, "undefined state at #{location}: '#{state}'"
112
336
  end # token = case state
113
337
 
114
338
  next unless token # allow functions to trigger redo w/ nil
115
339
  end # while
116
340
 
117
- raise "bad lexical result: #{token.inspect}" unless
341
+ raise LexerError, "bad lexical result at #{location}: #{token.inspect}" unless
118
342
  token.nil? || (Array === token && token.size >= 2)
119
343
 
120
344
  # auto-switch state
@@ -123,6 +347,8 @@ class Rubex::Lexer
123
347
  token
124
348
  end # def next_token
125
349
  def do_parse
350
+ self.ss.string = self.ss.string.split("\n").map! { |e| e.rstrip }.join("\n")
351
+ self.ss << "\n"
126
352
  end
127
353
  end # class
128
354