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