rubex 0.0.1 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|