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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.travis.yml +14 -0
- data/CONTRIBUTING.md +101 -0
- data/HISTORY.md +3 -0
- data/README.md +112 -297
- data/REFERENCE.md +753 -0
- data/Rakefile +4 -1
- data/TUTORIAL.md +234 -0
- data/bin/rubex +1 -1
- data/docs/_config.yml +1 -0
- data/docs/index.html +1 -0
- data/examples/c_struct_interface/c_struct_interface.rb +6 -0
- data/examples/c_struct_interface/c_struct_interface.rubex +47 -0
- data/examples/linked_list/linked_list.rubex +39 -0
- data/examples/linked_list/rb_linked_list.rb +8 -0
- data/examples/rcsv wrapper/rcsv/README.md +1 -0
- data/examples/rcsv wrapper/rcsv/Rakefile +7 -0
- data/examples/rcsv wrapper/rcsv/ext/rcsv/extconf.rb +3 -0
- data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.c +302 -0
- data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.rubex +124 -0
- data/examples/rcsv wrapper/rcsv/lib/rcsv.rb +8 -0
- data/examples/rcsv wrapper/rcsv/lib/rcsv.so +0 -0
- data/examples/rcsv wrapper/rcsv/lib/rcsv/version.rb +1 -0
- data/examples/rcsv wrapper/rcsv/rcsv.gemspec +27 -0
- data/examples/rcsv wrapper/rcsv/spec/rcsv.csv +5 -0
- data/examples/rcsv wrapper/rcsv/spec/rcsv_spec.rb +17 -0
- data/examples/rcsv wrapper/rcsv/spec/spec_helper.rb +6 -0
- data/{spec/fixtures/basic_ruby_method/Makefile → examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/Makefile } +20 -20
- data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.o +0 -0
- data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.so +0 -0
- data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/stage/lib/rcsv.so +0 -0
- data/lib/rubex.rb +6 -50
- data/lib/rubex/ast.rb +1 -3
- data/lib/rubex/ast/expression.rb +1257 -8
- data/lib/rubex/ast/node.rb +226 -28
- data/lib/rubex/ast/statement.rb +1162 -35
- data/lib/rubex/ast/top_statement.rb +815 -0
- data/lib/rubex/code_writer.rb +103 -26
- data/lib/rubex/compiler.rb +72 -0
- data/lib/rubex/compiler_config.rb +19 -0
- data/lib/rubex/constants.rb +145 -8
- data/lib/rubex/data_type.rb +667 -4
- data/lib/rubex/error.rb +15 -0
- data/lib/rubex/helpers.rb +154 -0
- data/lib/rubex/lexer.rex +186 -22
- data/lib/rubex/lexer.rex.rb +261 -35
- data/lib/rubex/parser.racc +876 -28
- data/lib/rubex/parser.racc.rb +2845 -90
- data/lib/rubex/rake_task.rb +34 -0
- data/lib/rubex/symbol_table/entry.rb +17 -3
- data/lib/rubex/symbol_table/scope.rb +298 -25
- data/lib/rubex/version.rb +1 -1
- data/rubex.gemspec +11 -3
- data/spec/basic_ruby_method_spec.rb +15 -21
- data/spec/binding_ptr_args_spec.rb +33 -0
- data/spec/bitwise_operators_spec.rb +40 -0
- data/spec/blocks_spec.rb +35 -0
- data/spec/c_bindings_spec.rb +36 -0
- data/spec/c_constants_spec.rb +33 -0
- data/spec/c_function_ptrs_spec.rb +38 -0
- data/spec/c_functions_spec.rb +35 -0
- data/spec/c_struct_interface_spec.rb +38 -0
- data/spec/call_by_reference_spec.rb +33 -0
- data/spec/class_methods_spec.rb +33 -0
- data/spec/class_spec.rb +40 -0
- data/spec/comments_spec.rb +33 -0
- data/spec/default_args_spec.rb +37 -0
- data/spec/error_handling_spec.rb +42 -0
- data/spec/examples_spec.rb +52 -0
- data/spec/expressions_spec.rb +33 -0
- data/spec/fixtures/basic_ruby_method/basic_ruby_method.rubex +2 -0
- data/spec/fixtures/binding_ptr_args/binding_ptr_args.rubex +30 -0
- data/spec/fixtures/bitwise_operators/bitwise_operators.rubex +40 -0
- data/spec/fixtures/blocks/blocks.rubex +11 -0
- data/spec/fixtures/c_bindings/c_bindings.rubex +58 -0
- data/spec/fixtures/c_constants/c_constants.rubex +7 -0
- data/spec/fixtures/c_function_ptrs/c_function_ptrs.rubex +52 -0
- data/spec/fixtures/c_functions/c_functions.rubex +25 -0
- data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +34 -0
- data/spec/fixtures/call_by_reference/call_by_reference.rubex +30 -0
- data/spec/fixtures/class/class.rubex +20 -0
- data/spec/fixtures/class_methods/class_methods.rubex +12 -0
- data/spec/fixtures/comments/comments.rubex +9 -0
- data/spec/fixtures/default_args/default_args.rubex +11 -0
- data/spec/fixtures/error_handling/error_handling.rubex +54 -0
- data/spec/fixtures/examples/array_to_hash.rubex +14 -0
- data/spec/fixtures/examples/rcsv.csv +5 -0
- data/spec/fixtures/examples/rcsv.rubex +329 -0
- data/spec/fixtures/expressions/expressions.rubex +10 -0
- data/spec/fixtures/if_else/if_else.rubex +77 -0
- data/spec/fixtures/implicit_lib_include/implicit_lib_include.rubex +15 -0
- data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +17 -0
- data/spec/fixtures/loops/loops.rubex +33 -0
- data/spec/fixtures/recursion/recursion.rubex +9 -0
- data/spec/fixtures/ruby_constant_method_calls/ruby_constant_method_calls.rubex +17 -0
- data/spec/fixtures/ruby_operators/ruby_operators.rubex +29 -0
- data/spec/fixtures/ruby_raise/ruby_raise.rubex +13 -0
- data/spec/fixtures/ruby_strings/ruby_strings.rubex +19 -0
- data/spec/fixtures/ruby_strings/string_blank_bm.rb +37 -0
- data/spec/fixtures/ruby_symbols/ruby_symbols.rubex +12 -0
- data/spec/fixtures/ruby_types/ruby_types.rubex +15 -0
- data/spec/fixtures/statement_expression/statement_expression.rubex +23 -0
- data/spec/fixtures/static_array/static_array.rubex +20 -0
- data/spec/fixtures/string_literals/string_literals.rubex +15 -0
- data/spec/fixtures/struct/struct.rubex +82 -0
- data/spec/fixtures/typecasting/typecasting.rubex +23 -0
- data/spec/fixtures/var_declarations/var_declarations.rubex +39 -0
- data/spec/if_else_spec.rb +39 -0
- data/spec/implicit_lib_include_spec.rb +33 -0
- data/spec/init_ruby_objects_with_literal_syntax_spec.rb +39 -0
- data/spec/loops_spec.rb +34 -0
- data/spec/recursion_spec.rb +35 -0
- data/spec/ruby_constant_method_calls_spec.rb +35 -0
- data/spec/ruby_operators_spec.rb +40 -0
- data/spec/ruby_raise_spec.rb +35 -0
- data/spec/ruby_strings_spec.rb +33 -0
- data/spec/ruby_symbols_spec.rb +37 -0
- data/spec/ruby_types_spec.rb +35 -0
- data/spec/spec_helper.rb +54 -1
- data/spec/statement_expression_spec.rb +34 -0
- data/spec/static_array_spec.rb +33 -0
- data/spec/string_literals_spec.rb +34 -0
- data/spec/struct_spec.rb +36 -0
- data/spec/typecasting_spec.rb +38 -0
- data/spec/var_declarions_spec.rb +35 -0
- metadata +255 -29
- data/lib/rubex/ast/argument_list.rb +0 -20
- data/lib/rubex/ast/c_base_type.rb +0 -11
- data/lib/rubex/ast/ruby_method_def.rb +0 -84
- data/spec/fixtures/basic_ruby_method/basic.rb +0 -3
- data/spec/fixtures/basic_ruby_method/basic_ruby_method.c +0 -16
- data/spec/fixtures/basic_ruby_method/basic_ruby_method.o +0 -0
- data/spec/fixtures/basic_ruby_method/basic_ruby_method.so +0 -0
- data/spec/fixtures/basic_ruby_method/extconf.rb +0 -3
data/lib/rubex/error.rb
ADDED
@@ -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
|
data/lib/rubex/lexer.rex
CHANGED
@@ -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-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
28
|
-
/#{
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
/#{
|
36
|
-
/#{
|
37
|
-
/#{
|
38
|
-
/#{
|
39
|
-
/#{
|
40
|
-
/#{
|
41
|
-
/#{
|
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
|
-
|
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
|
data/lib/rubex/lexer.rex.rb
CHANGED
@@ -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
|
+
# 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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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(
|
73
|
-
action { [:
|
74
|
-
when text = ss.scan(/
|
75
|
-
action { [:
|
76
|
-
when text = ss.scan(/#{
|
77
|
-
action { [:
|
78
|
-
when
|
79
|
-
action {
|
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(/#{
|
87
|
-
action { [:
|
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(/#{
|
95
|
-
action { [:
|
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.
|
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
|
|