fancy 0.3.0
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.
- data/AUTHORS +7 -0
- data/LICENSE +19 -0
- data/README +173 -0
- data/Rakefile +255 -0
- data/bin/fancy +40 -0
- data/bin/fdoc +23 -0
- data/bin/fyi +22 -0
- data/bin/ifancy +46 -0
- data/boot/README +12 -0
- data/boot/code_loader.rb +165 -0
- data/boot/compile.fy +3 -0
- data/boot/fancy_ext.rb +13 -0
- data/boot/fancy_ext/block_env.rb +29 -0
- data/boot/fancy_ext/class.rb +26 -0
- data/boot/fancy_ext/kernel.rb +12 -0
- data/boot/fancy_ext/module.rb +89 -0
- data/boot/fancy_ext/object.rb +34 -0
- data/boot/fancy_ext/string_helper.rb +10 -0
- data/boot/load.rb +72 -0
- data/boot/rbx-compiler/README +12 -0
- data/boot/rbx-compiler/compiler.rb +24 -0
- data/boot/rbx-compiler/compiler/ast.rb +23 -0
- data/boot/rbx-compiler/compiler/ast/README +11 -0
- data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
- data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
- data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
- data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
- data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
- data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
- data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
- data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
- data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
- data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
- data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
- data/boot/rbx-compiler/compiler/command.rb +39 -0
- data/boot/rbx-compiler/compiler/compiler.rb +83 -0
- data/boot/rbx-compiler/compiler/stages.rb +99 -0
- data/boot/rbx-compiler/parser.rb +2 -0
- data/boot/rbx-compiler/parser/README +15 -0
- data/boot/rbx-compiler/parser/Rakefile +54 -0
- data/boot/rbx-compiler/parser/extconf.rb +3 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
- data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
- data/boot/rbx-compiler/parser/lexer.lex +180 -0
- data/boot/rbx-compiler/parser/parser.rb +356 -0
- data/boot/rbx-compiler/parser/parser.y +711 -0
- data/boot/rsexp_pretty_printer.rb +76 -0
- data/doc/api/fancy.css +93 -0
- data/doc/api/fancy.jsonp +1 -0
- data/doc/api/fdoc.js +187 -0
- data/doc/api/index.html +57 -0
- data/doc/api/underscore-min.js +18 -0
- data/doc/features.md +228 -0
- data/examples/argv.fy +8 -0
- data/examples/arithmetic.fy +7 -0
- data/examples/armstrong_numbers.fy +33 -0
- data/examples/array.fy +52 -0
- data/examples/blocks.fy +15 -0
- data/examples/boolean.fy +24 -0
- data/examples/call_with_receiver.fy +9 -0
- data/examples/class.fy +68 -0
- data/examples/closures.fy +24 -0
- data/examples/constant_access.fy +15 -0
- data/examples/default_args.fy +17 -0
- data/examples/define_methods.fy +15 -0
- data/examples/documentation.fy +57 -0
- data/examples/documentation_formatters.fy +25 -0
- data/examples/echo.fy +16 -0
- data/examples/empty_catch.fy +4 -0
- data/examples/exception.fy +9 -0
- data/examples/factorial.fy +12 -0
- data/examples/fibonacci.fy +16 -0
- data/examples/files.fy +23 -0
- data/examples/finally.fy +5 -0
- data/examples/game_of_life.fy +148 -0
- data/examples/hashes.fy +7 -0
- data/examples/hello_world.fy +6 -0
- data/examples/html_generator.fy +54 -0
- data/examples/implicit_return.fy +3 -0
- data/examples/matchers.fy +6 -0
- data/examples/methods.fy +29 -0
- data/examples/nested_classes.fy +27 -0
- data/examples/nested_try.fy +9 -0
- data/examples/numbers.fy +12 -0
- data/examples/pattern_matching.fy +40 -0
- data/examples/person.fy +65 -0
- data/examples/project-euler/01.fy +8 -0
- data/examples/project-euler/02.fy +21 -0
- data/examples/project-euler/28.fy +33 -0
- data/examples/rbx/and_or.fy +7 -0
- data/examples/rbx/blocks.fy +22 -0
- data/examples/rbx/classes.fy +32 -0
- data/examples/rbx/hello.fy +8 -0
- data/examples/rbx/include.fy +12 -0
- data/examples/rbx/inherit.fy +11 -0
- data/examples/rbx/methods.fy +15 -0
- data/examples/rbx/nested_classes.fy +9 -0
- data/examples/rbx/require.fy +3 -0
- data/examples/rbx/strings.fy +5 -0
- data/examples/regex.fy +7 -0
- data/examples/require.fy +7 -0
- data/examples/retry.fy +12 -0
- data/examples/return.fy +13 -0
- data/examples/ruby_require.fy +7 -0
- data/examples/ruby_send.fy +3 -0
- data/examples/singleton_methods.fy +21 -0
- data/examples/stupid_quicksort.fy +12 -0
- data/examples/threads.fy +18 -0
- data/examples/tuple.fy +8 -0
- data/examples/webserver/webserver.fy +18 -0
- data/lib/argv.fy +36 -0
- data/lib/array.fy +207 -0
- data/lib/block.fy +88 -0
- data/lib/boot.fy +41 -0
- data/lib/class.fy +106 -0
- data/lib/compiler.fy +14 -0
- data/lib/compiler/ast.fy +40 -0
- data/lib/compiler/ast/assign.fy +96 -0
- data/lib/compiler/ast/block.fy +84 -0
- data/lib/compiler/ast/class_def.fy +33 -0
- data/lib/compiler/ast/expression_list.fy +47 -0
- data/lib/compiler/ast/identifier.fy +113 -0
- data/lib/compiler/ast/literals.fy +122 -0
- data/lib/compiler/ast/match.fy +88 -0
- data/lib/compiler/ast/message_send.fy +110 -0
- data/lib/compiler/ast/method_def.fy +90 -0
- data/lib/compiler/ast/node.fy +7 -0
- data/lib/compiler/ast/range.fy +16 -0
- data/lib/compiler/ast/require.fy +15 -0
- data/lib/compiler/ast/return.fy +23 -0
- data/lib/compiler/ast/script.fy +52 -0
- data/lib/compiler/ast/singleton_method_def.fy +35 -0
- data/lib/compiler/ast/super.fy +17 -0
- data/lib/compiler/ast/try_catch.fy +176 -0
- data/lib/compiler/ast/tuple_literal.fy +34 -0
- data/lib/compiler/command.fy +51 -0
- data/lib/compiler/compiler.fy +73 -0
- data/lib/compiler/stages.fy +81 -0
- data/lib/directory.fy +17 -0
- data/lib/documentation.fy +115 -0
- data/lib/enumerable.fy +269 -0
- data/lib/eval.fy +31 -0
- data/lib/fancy_spec.fy +202 -0
- data/lib/fdoc.fy +359 -0
- data/lib/fdoc_hook.fy +10 -0
- data/lib/file.fy +54 -0
- data/lib/hash.fy +56 -0
- data/lib/main.fy +80 -0
- data/lib/method.fy +22 -0
- data/lib/nil_class.fy +56 -0
- data/lib/number.fy +87 -0
- data/lib/object.fy +170 -0
- data/lib/package.fy +61 -0
- data/lib/package/dependency.fy +24 -0
- data/lib/package/installer.fy +180 -0
- data/lib/package/specification.fy +55 -0
- data/lib/package/uninstaller.fy +15 -0
- data/lib/parser.fy +4 -0
- data/lib/parser/ext/README +15 -0
- data/lib/parser/ext/ext.c +42 -0
- data/lib/parser/ext/ext.h +8 -0
- data/lib/parser/ext/extconf.rb +3 -0
- data/lib/parser/ext/lexer.lex +187 -0
- data/lib/parser/ext/parser.y +744 -0
- data/lib/parser/methods.fy +297 -0
- data/lib/rbx.fy +37 -0
- data/lib/rbx/array.fy +237 -0
- data/lib/rbx/bignum.fy +23 -0
- data/lib/rbx/block.fy +9 -0
- data/lib/rbx/class.fy +129 -0
- data/lib/rbx/code_loader.fy +192 -0
- data/lib/rbx/console.fy +63 -0
- data/lib/rbx/directory.fy +46 -0
- data/lib/rbx/documentation.fy +64 -0
- data/lib/rbx/environment_variables.fy +3 -0
- data/lib/rbx/exception.fy +30 -0
- data/lib/rbx/false_class.fy +58 -0
- data/lib/rbx/fiber.fy +25 -0
- data/lib/rbx/file.fy +191 -0
- data/lib/rbx/fixnum.fy +25 -0
- data/lib/rbx/float.fy +14 -0
- data/lib/rbx/hash.fy +38 -0
- data/lib/rbx/integer.fy +15 -0
- data/lib/rbx/io.fy +30 -0
- data/lib/rbx/match_data.fy +9 -0
- data/lib/rbx/method.fy +22 -0
- data/lib/rbx/name_error.fy +3 -0
- data/lib/rbx/no_method_error.fy +15 -0
- data/lib/rbx/object.fy +117 -0
- data/lib/rbx/range.fy +15 -0
- data/lib/rbx/regexp.fy +9 -0
- data/lib/rbx/string.fy +63 -0
- data/lib/rbx/symbol.fy +12 -0
- data/lib/rbx/system.fy +37 -0
- data/lib/rbx/tcp_server.fy +6 -0
- data/lib/rbx/tcp_socket.fy +7 -0
- data/lib/rbx/thread.fy +75 -0
- data/lib/rbx/tuple.fy +37 -0
- data/lib/set.fy +61 -0
- data/lib/stack.fy +51 -0
- data/lib/string.fy +58 -0
- data/lib/struct.fy +13 -0
- data/lib/symbol.fy +23 -0
- data/lib/true_class.fy +43 -0
- data/lib/tuple.fy +68 -0
- data/lib/version.fy +6 -0
- data/tests/argv.fy +13 -0
- data/tests/array.fy +343 -0
- data/tests/assignment.fy +53 -0
- data/tests/block.fy +103 -0
- data/tests/class.fy +409 -0
- data/tests/control_flow.fy +79 -0
- data/tests/documentation.fy +24 -0
- data/tests/exception.fy +115 -0
- data/tests/file.fy +86 -0
- data/tests/hash.fy +101 -0
- data/tests/method.fy +131 -0
- data/tests/nil_class.fy +55 -0
- data/tests/number.fy +128 -0
- data/tests/object.fy +125 -0
- data/tests/parsing/sexp.fy +50 -0
- data/tests/pattern_matching.fy +82 -0
- data/tests/range.fy +11 -0
- data/tests/set.fy +10 -0
- data/tests/stack.fy +22 -0
- data/tests/string.fy +102 -0
- data/tests/symbol.fy +17 -0
- data/tests/true_class.fy +63 -0
- data/tests/tuple.fy +21 -0
- data/tools/fancy-mode.el +63 -0
- metadata +321 -0
@@ -0,0 +1,356 @@
|
|
1
|
+
|
2
|
+
class Fancy
|
3
|
+
|
4
|
+
# This module has methods that can be used as callbacks from
|
5
|
+
# the parser, so that we can have a relatively simple fancy.y
|
6
|
+
# For example, when the parser sees a literal (or any other node)
|
7
|
+
# it just calls methods defined here. that create actual
|
8
|
+
# AST nodes, returning them to the parser to be stored on
|
9
|
+
# $$
|
10
|
+
class Parser
|
11
|
+
|
12
|
+
class ParseError < StandardError; end
|
13
|
+
|
14
|
+
def self.parse_file(filename, lineno = 1)
|
15
|
+
new(filename, lineno).parse_file.script
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse_string(code, lineno = 1, filename = "(eval)")
|
19
|
+
new(filename, lineno).parse_string(code).script
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :filename, :lineno, :script
|
23
|
+
|
24
|
+
def initialize(filename, lineno)
|
25
|
+
@filename, @lineno = filename, lineno
|
26
|
+
end
|
27
|
+
|
28
|
+
def body=(expression_list)
|
29
|
+
@script = AST::Script.new(lineno, filename, expression_list)
|
30
|
+
end
|
31
|
+
|
32
|
+
def string_literal(line, yytext)
|
33
|
+
str = yytext[1..-2] # omit the starting and ending quotes
|
34
|
+
AST::StringLiteral.new(line, str)
|
35
|
+
end
|
36
|
+
|
37
|
+
def multiline_string_literal(line, yytext)
|
38
|
+
str = yytext[3..-4] # omit the starting and ending triple-quotes
|
39
|
+
AST::StringLiteral.new(line, str)
|
40
|
+
end
|
41
|
+
|
42
|
+
def integer_literal(line, yytext, base = 10)
|
43
|
+
AST::FixnumLiteral.new(line, yytext.to_i(base))
|
44
|
+
end
|
45
|
+
|
46
|
+
def double_literal(line, yytext)
|
47
|
+
AST::NumberLiteral.new(line, yytext.to_f)
|
48
|
+
end
|
49
|
+
|
50
|
+
def symbol_literal(line, yytext)
|
51
|
+
str = yytext[1..-1] # omit the quote
|
52
|
+
AST::SymbolLiteral.new(line, str.to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_error(line, yytext)
|
56
|
+
raise ParseError.new "Parse error at line #{line}, unexpected token: #{yytext.inspect}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def file_error(*error)
|
60
|
+
raise ParseError.new error.join(" ")
|
61
|
+
end
|
62
|
+
|
63
|
+
def const_identifier(line, identifier, parent = nil)
|
64
|
+
if parent
|
65
|
+
AST::ScopedConstant.new(line, parent, identifier.name)
|
66
|
+
else
|
67
|
+
identifier
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def ruby_send_open(line, yytext)
|
72
|
+
# A ruby send is identified by the parser by seeing an
|
73
|
+
# identifier immediatly followed by a left-paren.
|
74
|
+
# NO SPACE IS ALLOWED BETWEEN THEM.
|
75
|
+
# So the parser gives yytext as the identifier with its
|
76
|
+
# left-paren as last character.
|
77
|
+
# Remove the paren and simply create an identifier.
|
78
|
+
identifier(line, yytext[0..-2])
|
79
|
+
end
|
80
|
+
|
81
|
+
def identifier(line, yytext)
|
82
|
+
if yytext == "self"
|
83
|
+
AST::Self.new(line)
|
84
|
+
else
|
85
|
+
AST::Identifier.new(line, yytext)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def msg_send_basic(line, receiver, identifier)
|
90
|
+
args = AST::MessageArgs.new(line)
|
91
|
+
AST::MessageSend.new(line, receiver, identifier, args)
|
92
|
+
end
|
93
|
+
|
94
|
+
def oper_send_basic(line, receiver, operator, argument)
|
95
|
+
args = AST::MessageArgs.new(line, argument)
|
96
|
+
AST::MessageSend.new(line, receiver, operator, args)
|
97
|
+
end
|
98
|
+
|
99
|
+
def assignment(line, identifier, value)
|
100
|
+
AST::Assignment.new(line, identifier, value)
|
101
|
+
end
|
102
|
+
|
103
|
+
def multiple_assignment(line, identifiers, values)
|
104
|
+
AST::MultipleAssignment.new(line, identifiers, values)
|
105
|
+
end
|
106
|
+
|
107
|
+
def identifier_list(line, identifier_list, identifier)
|
108
|
+
if identifier_list.kind_of?(Array)
|
109
|
+
identifier_list.push(identifier)
|
110
|
+
else
|
111
|
+
[identifier_list, identifier]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def send_args(line, selector, value, ary = [])
|
116
|
+
selector = AST::Identifier.new(selector.line, selector.identifier+":")
|
117
|
+
ary.push Struct.new(:selector, :value).new(selector, value)
|
118
|
+
end
|
119
|
+
|
120
|
+
def operator_def(line, operator, parameter, method_body, access = :public)
|
121
|
+
args = AST::MethodArgs.new(line, parameter.identifier)
|
122
|
+
AST::MethodDef.new(line, operator, args, method_body, access)
|
123
|
+
end
|
124
|
+
|
125
|
+
def sin_operator_def(line, identifier, operator, parameter, method_body, access = :public)
|
126
|
+
args = AST::MethodArgs.new(line, parameter.identifier)
|
127
|
+
AST::SingletonMethodDef.new(line, identifier, operator, args, method_body, access)
|
128
|
+
end
|
129
|
+
|
130
|
+
def method_def_no_args(line, method_ident, method_body, access = :public)
|
131
|
+
args = AST::MethodArgs.new(line)
|
132
|
+
AST::MethodDef.new(line, method_ident, args, method_body, access)
|
133
|
+
end
|
134
|
+
|
135
|
+
def method_arg(line, selector, variable, default = nil)
|
136
|
+
selector = AST::Identifier.new(selector.line, selector.identifier+":")
|
137
|
+
Struct.new(:selector, :variable, :default).new(selector, variable, default)
|
138
|
+
end
|
139
|
+
|
140
|
+
def helper_method_name(method_args)
|
141
|
+
method_args.map { |a| a.selector.identifier }.join("")
|
142
|
+
end
|
143
|
+
|
144
|
+
# Creates a single MethodDef node.
|
145
|
+
def method_def(line, method_args, method_body, access)
|
146
|
+
name = helper_method_name(method_args)
|
147
|
+
method_ident = AST::Identifier.new(line, name)
|
148
|
+
args = method_args.map { |a| a.variable.identifier }
|
149
|
+
args = AST::MethodArgs.new(line, *args)
|
150
|
+
AST::MethodDef.new(line, method_ident, args, method_body, access)
|
151
|
+
end
|
152
|
+
|
153
|
+
def method_delegators(method_args)
|
154
|
+
# find the first default argument
|
155
|
+
idx = method_args.index { |a| a.default }
|
156
|
+
return unless idx
|
157
|
+
|
158
|
+
line = method_args.first.selector.line
|
159
|
+
target = helper_method_name(method_args)
|
160
|
+
|
161
|
+
(method_args.size - idx).times do |pos|
|
162
|
+
|
163
|
+
required = method_args[0...idx+pos]
|
164
|
+
default = method_args[idx+pos..-1]
|
165
|
+
|
166
|
+
params = required.map(&:variable) + default.map(&:default)
|
167
|
+
|
168
|
+
forward = AST::MessageSend.new(line,
|
169
|
+
AST::Self.new(line),
|
170
|
+
AST::Identifier.new(line, target),
|
171
|
+
AST::MessageArgs.new(line, *params))
|
172
|
+
doc = AST::StringLiteral.new(line, "Forward to message #{target}")
|
173
|
+
body = AST::ExpressionList.new(line, doc, forward)
|
174
|
+
|
175
|
+
yield required, body
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
# Generate an expression list of method_defs
|
181
|
+
def method_def_expand(line, method_args, method_body, access = :public)
|
182
|
+
defs = []
|
183
|
+
method_delegators(method_args) do |sel, fwd|
|
184
|
+
defs << method_def(line, sel, fwd, access)
|
185
|
+
end
|
186
|
+
defs << method_def(line, method_args, method_body, access)
|
187
|
+
AST::ExpressionList.new(line, *defs)
|
188
|
+
end
|
189
|
+
|
190
|
+
def sin_method_def_expand(line, identifier, method_args, method_body, access = :public)
|
191
|
+
defs = []
|
192
|
+
method_delegators(method_args) do |sel, fwd|
|
193
|
+
defs << sin_method_def(line, identifier, sel, fwd, access)
|
194
|
+
end
|
195
|
+
defs << sin_method_def(line, identifier, method_args, method_body, access)
|
196
|
+
AST::ExpressionList.new(line, *defs)
|
197
|
+
end
|
198
|
+
|
199
|
+
def sin_method_def(line, identifier, method_args, method_body, access = :public)
|
200
|
+
name = method_args.map { |a| a.selector.identifier }.join("")
|
201
|
+
method_name = AST::Identifier.new(line, name)
|
202
|
+
args = method_args.map { |a| a.variable.identifier }
|
203
|
+
args = AST::MethodArgs.new(line, *args)
|
204
|
+
AST::SingletonMethodDef.new(line, identifier, method_name, args, method_body, access)
|
205
|
+
end
|
206
|
+
|
207
|
+
def sin_method_def_no_args(line, identifier, method_name, method_body, access = :public)
|
208
|
+
args = AST::MethodArgs.new(line)
|
209
|
+
AST::SingletonMethodDef.new(line, identifier, method_name, args, method_body, access)
|
210
|
+
end
|
211
|
+
|
212
|
+
def msg_send_args(line, receiver, method_args)
|
213
|
+
receiver ||= AST::Self.new(line)
|
214
|
+
name = method_args.map { |a| a.selector.identifier }.join("")
|
215
|
+
name = AST::Identifier.new(line, name)
|
216
|
+
args = AST::MessageArgs.new line, *method_args.map { |a| a.value }
|
217
|
+
AST::MessageSend.new(line, receiver, name, args)
|
218
|
+
end
|
219
|
+
|
220
|
+
def msg_send_ruby(line, receiver, identifier, args = nil)
|
221
|
+
receiver ||= AST::Self.new(line)
|
222
|
+
args ||= ruby_args(line)
|
223
|
+
arguments = AST::MessageArgs.new line, args
|
224
|
+
AST::MessageSend.new(line, receiver, identifier, arguments)
|
225
|
+
end
|
226
|
+
|
227
|
+
def nil_literal(line)
|
228
|
+
Rubinius::AST::NilLiteral.new(line)
|
229
|
+
end
|
230
|
+
|
231
|
+
def block_literal(line, block_args, block_body)
|
232
|
+
block_args ||= Array.new
|
233
|
+
args = AST::BlockArgs.new line, *block_args
|
234
|
+
AST::BlockLiteral.new(line, args, block_body)
|
235
|
+
end
|
236
|
+
|
237
|
+
def tuple_literal(line, expr_ary = [])
|
238
|
+
# when we have a tuple with 1 element, it's not actually a tuple
|
239
|
+
# but a grouped expression, e.g. (obj foo: bar)
|
240
|
+
# 1-tuples don't make much sense anyway, so we won't support
|
241
|
+
# them via tuple literal syntax.
|
242
|
+
if expr_ary.size == 1
|
243
|
+
expr_ary.first
|
244
|
+
else
|
245
|
+
AST::TupleLiteral.new(line, *expr_ary)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def range_literal(line, from, to)
|
250
|
+
AST::RangeLiteral.new(line, from, to)
|
251
|
+
end
|
252
|
+
|
253
|
+
def block_args(line, identifier, ary = [])
|
254
|
+
ary.push identifier
|
255
|
+
end
|
256
|
+
|
257
|
+
def expr_list(line, expr = nil, expr_list = nil)
|
258
|
+
expr_list = AST::ExpressionList.new(line) unless expr_list
|
259
|
+
expr_list.add_expression(expr) if expr
|
260
|
+
expr_list
|
261
|
+
end
|
262
|
+
|
263
|
+
def class_def(line, name, parent, body)
|
264
|
+
AST::ClassDef.new(line, name, parent, body)
|
265
|
+
end
|
266
|
+
|
267
|
+
def expr_ary(line, exp, ary = [])
|
268
|
+
if exp.is_a? Array
|
269
|
+
ary += exp
|
270
|
+
else
|
271
|
+
ary.push exp
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def array_literal(line, expr_ary = [])
|
276
|
+
AST::ArrayLiteral.new(line, *expr_ary)
|
277
|
+
end
|
278
|
+
|
279
|
+
def ruby_args(line, array_literal = nil, block = nil)
|
280
|
+
if array_literal.kind_of?(Array)
|
281
|
+
array_literal = AST::ArrayLiteral.new(line, *array_literal)
|
282
|
+
end
|
283
|
+
if array_literal.nil?
|
284
|
+
array_literal = AST::ArrayLiteral.new(line)
|
285
|
+
end
|
286
|
+
AST::RubyArgs.new(line, array_literal, block)
|
287
|
+
end
|
288
|
+
|
289
|
+
def super_exp(line)
|
290
|
+
AST::Super.new(line)
|
291
|
+
end
|
292
|
+
|
293
|
+
def retry_exp(line)
|
294
|
+
AST::Retry.new(line)
|
295
|
+
end
|
296
|
+
|
297
|
+
def catch_handlers(line, handler = nil, handlers = nil)
|
298
|
+
handlers ||= AST::Handlers.new(line)
|
299
|
+
handlers.add_handler handler if handler
|
300
|
+
handlers
|
301
|
+
end
|
302
|
+
|
303
|
+
def catch_handler(line, body = nil, condition = nil, var = nil)
|
304
|
+
condition ||= AST::Identifier.new(line, "Object")
|
305
|
+
AST::ExceptHandler.new(line, condition, var, body)
|
306
|
+
end
|
307
|
+
|
308
|
+
def try_catch_finally(line, body, handlers, finally = nil)
|
309
|
+
handlers ||= AST::Handlers.new(line)
|
310
|
+
AST::TryCatchBlock.new(line, body, handlers, finally)
|
311
|
+
end
|
312
|
+
|
313
|
+
def key_value_list(line, key, value, ary = [])
|
314
|
+
ary.push key
|
315
|
+
ary.push value
|
316
|
+
ary
|
317
|
+
end
|
318
|
+
|
319
|
+
def hash_literal(line, key_values = [])
|
320
|
+
AST::HashLiteral.new(line, *key_values)
|
321
|
+
end
|
322
|
+
|
323
|
+
def regex_literal(line, regexp_str)
|
324
|
+
regexp_str = regexp_str[1..-2]
|
325
|
+
AST::RegexLiteral.new(line, regexp_str, 0)
|
326
|
+
end
|
327
|
+
|
328
|
+
def require_stmt(line, identifier)
|
329
|
+
AST::Require.new(line, identifier)
|
330
|
+
end
|
331
|
+
|
332
|
+
def return_stmt(line, expr = nil)
|
333
|
+
expr ||= nil_literal(expr)
|
334
|
+
AST::Return.new(line, expr)
|
335
|
+
end
|
336
|
+
|
337
|
+
def return_local(line, expr = nil)
|
338
|
+
expr ||= nil_literal(expr)
|
339
|
+
AST::Return.new(line, expr)
|
340
|
+
end
|
341
|
+
|
342
|
+
def match_expr(line, expr, clauses = nil)
|
343
|
+
clauses ||= []
|
344
|
+
AST::Match.new(line, expr, clauses)
|
345
|
+
end
|
346
|
+
|
347
|
+
def match_body(line, match_clause, match_clauses = [])
|
348
|
+
match_clauses.push(match_clause)
|
349
|
+
end
|
350
|
+
|
351
|
+
def match_clause(line, match_expr, val_expr, match_arg=nil)
|
352
|
+
AST::MatchClause.new(line, match_expr, val_expr, match_arg)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
@@ -0,0 +1,711 @@
|
|
1
|
+
%{
|
2
|
+
#include "ruby.h"
|
3
|
+
|
4
|
+
int yyerror(VALUE, char *s);
|
5
|
+
int yylex(VALUE);
|
6
|
+
|
7
|
+
VALUE fy_terminal_node(VALUE, char *);
|
8
|
+
VALUE fy_terminal_node_from(VALUE, char *, char*);
|
9
|
+
|
10
|
+
extern int yylineno;
|
11
|
+
extern char *yytext;
|
12
|
+
|
13
|
+
%}
|
14
|
+
|
15
|
+
%lex-param { VALUE self }
|
16
|
+
%parse-param { VALUE self }
|
17
|
+
|
18
|
+
%union{
|
19
|
+
VALUE object;
|
20
|
+
ID symbol;
|
21
|
+
}
|
22
|
+
|
23
|
+
%start programm
|
24
|
+
|
25
|
+
%token LPAREN
|
26
|
+
%token RPAREN
|
27
|
+
%token LCURLY
|
28
|
+
%token RCURLY
|
29
|
+
%token LBRACKET
|
30
|
+
%token RBRACKET
|
31
|
+
%token LHASH
|
32
|
+
%token RHASH
|
33
|
+
%token STAB
|
34
|
+
%token ARROW
|
35
|
+
%token THIN_ARROW
|
36
|
+
%token COMMA
|
37
|
+
%token SEMI
|
38
|
+
%token NL
|
39
|
+
%token COLON
|
40
|
+
%token RETURN_LOCAL
|
41
|
+
%token RETURN
|
42
|
+
%token REQUIRE
|
43
|
+
%token TRY
|
44
|
+
%token CATCH
|
45
|
+
%token FINALLY
|
46
|
+
%token RETRY
|
47
|
+
%token SUPER
|
48
|
+
%token PRIVATE
|
49
|
+
%token PROTECTED
|
50
|
+
%token CLASS
|
51
|
+
%token DEF
|
52
|
+
%token DOT
|
53
|
+
%token DOLLAR
|
54
|
+
%token EQUALS
|
55
|
+
%token MATCH
|
56
|
+
%token CASE
|
57
|
+
%token IDENTIFIER
|
58
|
+
%token RUBY_SEND_OPEN
|
59
|
+
%token RUBY_OPER_OPEN
|
60
|
+
%token CONSTANT
|
61
|
+
|
62
|
+
%token INTEGER_LITERAL
|
63
|
+
%token HEX_LITERAL
|
64
|
+
%token OCT_LITERAL
|
65
|
+
%token BIN_LITERAL
|
66
|
+
%token DOUBLE_LITERAL
|
67
|
+
%token STRING_LITERAL
|
68
|
+
%token MULTI_STRING_LITERAL
|
69
|
+
%token SYMBOL_LITERAL
|
70
|
+
%token REGEX_LITERAL
|
71
|
+
%token OPERATOR
|
72
|
+
|
73
|
+
%left DOT
|
74
|
+
%right DOLLAR
|
75
|
+
|
76
|
+
%type <object> integer_literal
|
77
|
+
%type <object> hex_literal
|
78
|
+
%type <object> oct_literal
|
79
|
+
%type <object> bin_literal
|
80
|
+
%type <object> double_literal
|
81
|
+
%type <object> string_literal
|
82
|
+
%type <object> symbol_literal
|
83
|
+
%type <object> regex_literal
|
84
|
+
%type <object> operator
|
85
|
+
|
86
|
+
|
87
|
+
%type <object> identifier
|
88
|
+
%type <object> any_identifier
|
89
|
+
%type <object> constant
|
90
|
+
%type <object> literal_value
|
91
|
+
%type <object> block_literal
|
92
|
+
%type <object> block_args
|
93
|
+
%type <object> block_args_without_comma
|
94
|
+
%type <object> block_args_with_comma
|
95
|
+
%type <object> hash_literal
|
96
|
+
%type <object> array_literal
|
97
|
+
%type <object> empty_array
|
98
|
+
%type <object> tuple_literal
|
99
|
+
%type <object> range_literal
|
100
|
+
|
101
|
+
%type <object> key_value_list
|
102
|
+
%type <object> exp_comma_list
|
103
|
+
|
104
|
+
%type <object> code
|
105
|
+
%type <object> expression_list
|
106
|
+
%type <object> expression_block
|
107
|
+
%type <object> exp
|
108
|
+
%type <object> assignment
|
109
|
+
%type <object> multiple_assignment
|
110
|
+
%type <object> identifier_list
|
111
|
+
%type <object> return_local_statement
|
112
|
+
%type <object> return_statement
|
113
|
+
%type <object> require_statement
|
114
|
+
|
115
|
+
%type <object> def
|
116
|
+
|
117
|
+
%type <object> const_identifier
|
118
|
+
%type <object> class_def
|
119
|
+
%type <object> class_no_super
|
120
|
+
%type <object> class_super
|
121
|
+
%type <object> class_method_w_args
|
122
|
+
%type <object> class_method_no_args
|
123
|
+
|
124
|
+
%type <object> method_def
|
125
|
+
%type <object> method_args
|
126
|
+
%type <object> method_arg
|
127
|
+
%type <object> method_args_default
|
128
|
+
%type <object> method_arg_default
|
129
|
+
%type <object> method_w_args
|
130
|
+
%type <object> method_no_args
|
131
|
+
%type <object> operator_def
|
132
|
+
%type <object> class_operator_def
|
133
|
+
|
134
|
+
%type <object> message_send
|
135
|
+
%type <object> ruby_send_open
|
136
|
+
%type <object> ruby_oper_open
|
137
|
+
%type <object> ruby_send
|
138
|
+
%type <object> ruby_oper_send
|
139
|
+
%type <object> ruby_args
|
140
|
+
%type <object> operator_send
|
141
|
+
%type <object> send_args
|
142
|
+
%type <object> arg_exp
|
143
|
+
|
144
|
+
%type <object> try_catch_block
|
145
|
+
%type <object> catch_blocks
|
146
|
+
%type <object> finally_block
|
147
|
+
%type <object> catch_block
|
148
|
+
%type <object> required_catch_blocks
|
149
|
+
|
150
|
+
%type <object> match_expr
|
151
|
+
%type <object> match_body
|
152
|
+
%type <object> match_clause
|
153
|
+
|
154
|
+
%%
|
155
|
+
|
156
|
+
programm: /*empty*/
|
157
|
+
| expression_list {
|
158
|
+
rb_funcall(self, rb_intern("body="), 1, $1);
|
159
|
+
}
|
160
|
+
;
|
161
|
+
|
162
|
+
delim: nls
|
163
|
+
| SEMI
|
164
|
+
| delim delim
|
165
|
+
;
|
166
|
+
|
167
|
+
nls: NL
|
168
|
+
| nls NL
|
169
|
+
;
|
170
|
+
|
171
|
+
space: /* */
|
172
|
+
| nls
|
173
|
+
;
|
174
|
+
|
175
|
+
code: statement
|
176
|
+
| exp
|
177
|
+
;
|
178
|
+
|
179
|
+
expression_list: code {
|
180
|
+
$$ = rb_funcall(self, rb_intern("expr_list"), 2, INT2NUM(yylineno), $1);
|
181
|
+
}
|
182
|
+
| expression_list code {
|
183
|
+
$$ = rb_funcall(self, rb_intern("expr_list"), 3, INT2NUM(yylineno), $2, $1);
|
184
|
+
}
|
185
|
+
| delim expression_list {
|
186
|
+
$$ = $2;
|
187
|
+
}
|
188
|
+
| expression_list delim {
|
189
|
+
$$ = $1;
|
190
|
+
}
|
191
|
+
;
|
192
|
+
|
193
|
+
expression_block: LCURLY space expression_list space RCURLY {
|
194
|
+
$$ = $3;
|
195
|
+
}
|
196
|
+
| LCURLY space RCURLY {
|
197
|
+
$$ = rb_funcall(self, rb_intern("expr_list"), 1, INT2NUM(yylineno));
|
198
|
+
}
|
199
|
+
;
|
200
|
+
|
201
|
+
statement: assignment
|
202
|
+
| return_local_statement
|
203
|
+
| return_statement
|
204
|
+
| require_statement
|
205
|
+
;
|
206
|
+
|
207
|
+
exp: method_def
|
208
|
+
| class_def
|
209
|
+
| try_catch_block
|
210
|
+
| match_expr
|
211
|
+
| message_send
|
212
|
+
| operator_send
|
213
|
+
| ruby_send
|
214
|
+
| ruby_oper_send
|
215
|
+
| literal_value
|
216
|
+
| any_identifier
|
217
|
+
| SUPER { $$ = rb_funcall(self, rb_intern("super_exp"), 1, INT2NUM(yylineno)); }
|
218
|
+
| RETRY { $$ = rb_funcall(self, rb_intern("retry_exp"), 1, INT2NUM(yylineno)); }
|
219
|
+
| LPAREN space exp space RPAREN {
|
220
|
+
$$ = $3;
|
221
|
+
}
|
222
|
+
| exp DOT space {
|
223
|
+
$$ = $1;
|
224
|
+
}
|
225
|
+
;
|
226
|
+
|
227
|
+
assignment: any_identifier EQUALS space exp {
|
228
|
+
$$ = rb_funcall(self, rb_intern("assignment"), 3, INT2NUM(yylineno), $1, $4);
|
229
|
+
}
|
230
|
+
| multiple_assignment
|
231
|
+
;
|
232
|
+
|
233
|
+
multiple_assignment: identifier_list EQUALS exp_comma_list {
|
234
|
+
$$ = rb_funcall(self, rb_intern("multiple_assignment"), 3, INT2NUM(yylineno), $1, $3);
|
235
|
+
}
|
236
|
+
;
|
237
|
+
|
238
|
+
operator: OPERATOR {
|
239
|
+
$$ = fy_terminal_node(self, "identifier");
|
240
|
+
}
|
241
|
+
;
|
242
|
+
|
243
|
+
constant: CONSTANT {
|
244
|
+
$$ = fy_terminal_node(self, "identifier");
|
245
|
+
}
|
246
|
+
;
|
247
|
+
|
248
|
+
identifier: IDENTIFIER {
|
249
|
+
$$ = fy_terminal_node(self, "identifier");
|
250
|
+
}
|
251
|
+
| MATCH {
|
252
|
+
$$ = fy_terminal_node_from(self, "identifier", "match");
|
253
|
+
}
|
254
|
+
| CLASS {
|
255
|
+
$$ = fy_terminal_node_from(self, "identifier", "class");
|
256
|
+
}
|
257
|
+
;
|
258
|
+
|
259
|
+
any_identifier: const_identifier
|
260
|
+
| identifier
|
261
|
+
;
|
262
|
+
|
263
|
+
identifier_list: any_identifier {
|
264
|
+
$$ = $1;
|
265
|
+
}
|
266
|
+
| identifier_list COMMA any_identifier {
|
267
|
+
$$ = rb_funcall(self, rb_intern("identifier_list"), 3, INT2NUM(yylineno), $1, $3);
|
268
|
+
}
|
269
|
+
;
|
270
|
+
|
271
|
+
return_local_statement: RETURN_LOCAL exp {
|
272
|
+
$$ = rb_funcall(self, rb_intern("return_local"), 2, INT2NUM(yylineno), $2);
|
273
|
+
}
|
274
|
+
| RETURN_LOCAL {
|
275
|
+
$$ = rb_funcall(self, rb_intern("return_local"), 1, INT2NUM(yylineno));
|
276
|
+
}
|
277
|
+
;
|
278
|
+
|
279
|
+
return_statement: RETURN exp {
|
280
|
+
$$ = rb_funcall(self, rb_intern("return_stmt"), 2, INT2NUM(yylineno), $2);
|
281
|
+
}
|
282
|
+
| RETURN {
|
283
|
+
$$ = rb_funcall(self, rb_intern("return_stmt"), 1, INT2NUM(yylineno));
|
284
|
+
}
|
285
|
+
;
|
286
|
+
|
287
|
+
require_statement: REQUIRE string_literal {
|
288
|
+
$$ = rb_funcall(self, rb_intern("require_stmt"), 2, INT2NUM(yylineno), $2);
|
289
|
+
}
|
290
|
+
| REQUIRE any_identifier {
|
291
|
+
$$ = rb_funcall(self, rb_intern("require_stmt"), 2, INT2NUM(yylineno), $2);
|
292
|
+
}
|
293
|
+
;
|
294
|
+
|
295
|
+
class_def: class_no_super
|
296
|
+
| class_super
|
297
|
+
;
|
298
|
+
|
299
|
+
const_identifier: constant {
|
300
|
+
$$ = rb_funcall(self, rb_intern("const_identifier"), 2, INT2NUM(yylineno), $1);
|
301
|
+
}
|
302
|
+
| const_identifier constant {
|
303
|
+
$$ = rb_funcall(self, rb_intern("const_identifier"), 3, INT2NUM(yylineno), $2, $1);
|
304
|
+
}
|
305
|
+
;
|
306
|
+
|
307
|
+
def: DEF PRIVATE { $$ = rb_intern("private"); }
|
308
|
+
| DEF PROTECTED { $$ = rb_intern("protected"); }
|
309
|
+
| DEF { $$ = rb_intern("public"); }
|
310
|
+
;
|
311
|
+
|
312
|
+
class_no_super: CLASS const_identifier expression_block {
|
313
|
+
$$ = rb_funcall(self, rb_intern("class_def"), 4, INT2NUM(yylineno), $2, Qnil, $3);
|
314
|
+
}
|
315
|
+
;
|
316
|
+
|
317
|
+
class_super: CLASS const_identifier COLON const_identifier expression_block {
|
318
|
+
$$ = rb_funcall(self, rb_intern("class_def"), 4, INT2NUM(yylineno), $2, $4, $5);
|
319
|
+
}
|
320
|
+
;
|
321
|
+
|
322
|
+
method_def: method_w_args
|
323
|
+
| method_no_args
|
324
|
+
| class_method_w_args
|
325
|
+
| class_method_no_args
|
326
|
+
| operator_def
|
327
|
+
| class_operator_def
|
328
|
+
;
|
329
|
+
|
330
|
+
method_arg: identifier COLON identifier {
|
331
|
+
$$ = rb_funcall(self, rb_intern("method_arg"), 3, INT2NUM(yylineno), $1, $3);
|
332
|
+
}
|
333
|
+
;
|
334
|
+
|
335
|
+
method_args: method_arg {
|
336
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 2, INT2NUM(yylineno), $1);
|
337
|
+
}
|
338
|
+
| method_args method_arg {
|
339
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 3, INT2NUM(yylineno), $2, $1);
|
340
|
+
}
|
341
|
+
| method_args method_args_default {
|
342
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 3, INT2NUM(yylineno), $2, $1);
|
343
|
+
}
|
344
|
+
;
|
345
|
+
|
346
|
+
method_arg_default: identifier COLON identifier LPAREN space exp space RPAREN {
|
347
|
+
$$ = rb_funcall(self, rb_intern("method_arg"), 4, INT2NUM(yylineno), $1, $3, $6);
|
348
|
+
}
|
349
|
+
;
|
350
|
+
|
351
|
+
method_args_default: method_arg_default {
|
352
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 2, INT2NUM(yylineno), $1);
|
353
|
+
}
|
354
|
+
| method_args_default space method_arg_default {
|
355
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 3, INT2NUM(yylineno), $3, $1);
|
356
|
+
}
|
357
|
+
;
|
358
|
+
|
359
|
+
method_w_args: def method_args expression_block {
|
360
|
+
$$ = rb_funcall(self, rb_intern("method_def_expand"), 4, INT2NUM(yylineno), $2, $3, $1);
|
361
|
+
}
|
362
|
+
;
|
363
|
+
|
364
|
+
|
365
|
+
method_no_args: def identifier expression_block {
|
366
|
+
$$ = rb_funcall(self, rb_intern("method_def_no_args"), 4, INT2NUM(yylineno), $2, $3, $1);
|
367
|
+
}
|
368
|
+
;
|
369
|
+
|
370
|
+
|
371
|
+
class_method_w_args: def any_identifier method_args expression_block {
|
372
|
+
$$ = rb_funcall(self, rb_intern("sin_method_def_expand"), 5, INT2NUM(yylineno), $2, $3, $4, $1);
|
373
|
+
}
|
374
|
+
;
|
375
|
+
|
376
|
+
class_method_no_args: def any_identifier identifier expression_block {
|
377
|
+
$$ = rb_funcall(self, rb_intern("sin_method_def_no_args"), 5, INT2NUM(yylineno), $2, $3, $4, $1);
|
378
|
+
}
|
379
|
+
;
|
380
|
+
|
381
|
+
operator_def: def operator identifier expression_block {
|
382
|
+
$$ = rb_funcall(self, rb_intern("operator_def"), 5, INT2NUM(yylineno), $2, $3, $4, $1);
|
383
|
+
}
|
384
|
+
| def LBRACKET RBRACKET identifier expression_block {
|
385
|
+
$$ = rb_funcall(self, rb_intern("operator_def"), 5,
|
386
|
+
INT2NUM(yylineno), fy_terminal_node_from(self, "identifier", "[]"), $4, $5, $1);
|
387
|
+
}
|
388
|
+
;
|
389
|
+
|
390
|
+
class_operator_def: def any_identifier operator identifier expression_block {
|
391
|
+
$$ = rb_funcall(self, rb_intern("sin_operator_def"), 6, INT2NUM(yylineno), $2, $3, $4, $5, $1);
|
392
|
+
}
|
393
|
+
| def any_identifier LBRACKET RBRACKET identifier expression_block {
|
394
|
+
$$ = rb_funcall(self, rb_intern("sin_operator_def"), 6,
|
395
|
+
INT2NUM(yylineno), $2, fy_terminal_node_from(self, "identifier", "[]"), $5, $6, $1);
|
396
|
+
}
|
397
|
+
;
|
398
|
+
|
399
|
+
message_send: exp identifier {
|
400
|
+
$$ = rb_funcall(self, rb_intern("msg_send_basic"), 3, INT2NUM(yylineno), $1, $2);
|
401
|
+
}
|
402
|
+
| exp send_args {
|
403
|
+
$$ = rb_funcall(self, rb_intern("msg_send_args"), 3, INT2NUM(yylineno), $1, $2);
|
404
|
+
}
|
405
|
+
| send_args {
|
406
|
+
$$ = rb_funcall(self, rb_intern("msg_send_args"), 3, INT2NUM(yylineno), Qnil, $1);
|
407
|
+
}
|
408
|
+
;
|
409
|
+
|
410
|
+
/* ruby_send_open is just an identifier immediatly followed by a left-paren
|
411
|
+
NO SPACE ALLOWED between the identifier and the left-paren. that's why we
|
412
|
+
need a parse rule.
|
413
|
+
*/
|
414
|
+
ruby_send_open: RUBY_SEND_OPEN {
|
415
|
+
// remove the trailing left paren and create an identifier.
|
416
|
+
$$ = fy_terminal_node(self, "ruby_send_open");
|
417
|
+
};
|
418
|
+
ruby_oper_open: RUBY_OPER_OPEN {
|
419
|
+
// remove the trailing left paren and create an identifier.
|
420
|
+
$$ = fy_terminal_node(self, "ruby_send_open");
|
421
|
+
};
|
422
|
+
|
423
|
+
ruby_send: exp ruby_send_open ruby_args {
|
424
|
+
$$ = rb_funcall(self, rb_intern("msg_send_ruby"), 4, INT2NUM(yylineno), $1, $2, $3);
|
425
|
+
}
|
426
|
+
| ruby_send_open ruby_args {
|
427
|
+
$$ = rb_funcall(self, rb_intern("msg_send_ruby"), 4, INT2NUM(yylineno), Qnil, $1, $2);
|
428
|
+
}
|
429
|
+
;
|
430
|
+
|
431
|
+
/*
|
432
|
+
The closing part of ruby_send_open.
|
433
|
+
We explicitly require parens for ALL ruby sends now, so there will always be
|
434
|
+
a closing paren.
|
435
|
+
*/
|
436
|
+
ruby_args: RPAREN block_literal {
|
437
|
+
$$ = rb_funcall(self, rb_intern("ruby_args"), 3, INT2NUM(yylineno), Qnil, $2);
|
438
|
+
}
|
439
|
+
| exp_comma_list RPAREN block_literal {
|
440
|
+
$$ = rb_funcall(self, rb_intern("ruby_args"), 3, INT2NUM(yylineno), $1, $3);
|
441
|
+
}
|
442
|
+
| RPAREN {
|
443
|
+
$$ = rb_funcall(self, rb_intern("ruby_args"), 1, INT2NUM(yylineno));
|
444
|
+
}
|
445
|
+
| exp_comma_list RPAREN {
|
446
|
+
$$ = rb_funcall(self, rb_intern("ruby_args"), 2, INT2NUM(yylineno), $1);
|
447
|
+
}
|
448
|
+
;
|
449
|
+
|
450
|
+
operator_send: exp operator arg_exp {
|
451
|
+
$$ = rb_funcall(self, rb_intern("oper_send_basic"), 4, INT2NUM(yylineno), $1, $2, $3);
|
452
|
+
}
|
453
|
+
| exp operator DOT space arg_exp {
|
454
|
+
$$ = rb_funcall(self, rb_intern("oper_send_basic"), 4, INT2NUM(yylineno), $1, $2, $5);
|
455
|
+
}
|
456
|
+
| exp LBRACKET exp RBRACKET {
|
457
|
+
$$ = rb_funcall(self, rb_intern("oper_send_basic"), 4,
|
458
|
+
INT2NUM(yylineno), $1, fy_terminal_node_from(self, "identifier", "[]"), $3);
|
459
|
+
}
|
460
|
+
;
|
461
|
+
|
462
|
+
ruby_oper_send: exp ruby_oper_open ruby_args {
|
463
|
+
$$ = rb_funcall(self, rb_intern("msg_send_ruby"), 4, INT2NUM(yylineno), $1, $2, $3);
|
464
|
+
}
|
465
|
+
;
|
466
|
+
|
467
|
+
|
468
|
+
send_args: identifier COLON arg_exp {
|
469
|
+
$$ = rb_funcall(self, rb_intern("send_args"), 3, INT2NUM(yylineno), $1, $3);
|
470
|
+
}
|
471
|
+
| identifier COLON space arg_exp {
|
472
|
+
$$ = rb_funcall(self, rb_intern("send_args"), 3, INT2NUM(yylineno), $1, $4);
|
473
|
+
}
|
474
|
+
| send_args identifier COLON arg_exp {
|
475
|
+
$$ = rb_funcall(self, rb_intern("send_args"), 4, INT2NUM(yylineno), $2, $4, $1);
|
476
|
+
}
|
477
|
+
| send_args identifier COLON space arg_exp {
|
478
|
+
$$ = rb_funcall(self, rb_intern("send_args"), 4, INT2NUM(yylineno), $2, $5, $1);
|
479
|
+
}
|
480
|
+
;
|
481
|
+
|
482
|
+
arg_exp: any_identifier {
|
483
|
+
$$ = $1;
|
484
|
+
}
|
485
|
+
| LPAREN exp RPAREN {
|
486
|
+
$$ = $2;
|
487
|
+
}
|
488
|
+
| literal_value {
|
489
|
+
$$ = $1;
|
490
|
+
}
|
491
|
+
| DOLLAR exp {
|
492
|
+
$$ = $2;
|
493
|
+
}
|
494
|
+
;
|
495
|
+
|
496
|
+
try_catch_block: TRY expression_block catch_blocks finally_block {
|
497
|
+
$$ = rb_funcall(self, rb_intern("try_catch_finally"), 4, INT2NUM(yylineno), $2, $3, $4);
|
498
|
+
}
|
499
|
+
| TRY expression_block required_catch_blocks {
|
500
|
+
$$ = rb_funcall(self, rb_intern("try_catch_finally"), 3, INT2NUM(yylineno), $2, $3);
|
501
|
+
}
|
502
|
+
;
|
503
|
+
|
504
|
+
catch_block: CATCH expression_block {
|
505
|
+
$$ = rb_funcall(self, rb_intern("catch_handler"), 2, INT2NUM(yylineno), $2);
|
506
|
+
}
|
507
|
+
| CATCH exp expression_block {
|
508
|
+
$$ = rb_funcall(self, rb_intern("catch_handler"), 3, INT2NUM(yylineno), $3, $2);
|
509
|
+
}
|
510
|
+
| CATCH exp ARROW identifier expression_block {
|
511
|
+
$$ = rb_funcall(self, rb_intern("catch_handler"), 4, INT2NUM(yylineno), $5, $2, $4);
|
512
|
+
}
|
513
|
+
;
|
514
|
+
|
515
|
+
required_catch_blocks: catch_block {
|
516
|
+
$$ = rb_funcall(self, rb_intern("catch_handlers"), 2, INT2NUM(yylineno), $1);
|
517
|
+
}
|
518
|
+
| required_catch_blocks catch_block {
|
519
|
+
$$ = rb_funcall(self, rb_intern("catch_handlers"), 3, INT2NUM(yylineno), $2, $1);
|
520
|
+
}
|
521
|
+
;
|
522
|
+
|
523
|
+
catch_blocks: catch_block {
|
524
|
+
$$ = rb_funcall(self, rb_intern("catch_handlers"), 2, INT2NUM(yylineno), $1);
|
525
|
+
}
|
526
|
+
| catch_blocks catch_block {
|
527
|
+
$$ = rb_funcall(self, rb_intern("catch_handlers"), 3, INT2NUM(yylineno), $2, $1);
|
528
|
+
}
|
529
|
+
| /* empty */ {
|
530
|
+
$$ = rb_funcall(self, rb_intern("catch_handlers"), 1, INT2NUM(yylineno));
|
531
|
+
}
|
532
|
+
;
|
533
|
+
|
534
|
+
finally_block: FINALLY expression_block {
|
535
|
+
$$ = $2;
|
536
|
+
}
|
537
|
+
;
|
538
|
+
|
539
|
+
integer_literal: INTEGER_LITERAL {
|
540
|
+
$$ = fy_terminal_node(self, "integer_literal");
|
541
|
+
}
|
542
|
+
;
|
543
|
+
double_literal: DOUBLE_LITERAL {
|
544
|
+
$$ = fy_terminal_node(self, "double_literal");
|
545
|
+
}
|
546
|
+
;
|
547
|
+
string_literal: STRING_LITERAL {
|
548
|
+
$$ = fy_terminal_node(self, "string_literal");
|
549
|
+
}
|
550
|
+
| MULTI_STRING_LITERAL {
|
551
|
+
$$ = fy_terminal_node(self, "multiline_string_literal");
|
552
|
+
}
|
553
|
+
;
|
554
|
+
symbol_literal: SYMBOL_LITERAL {
|
555
|
+
$$ = fy_terminal_node(self, "symbol_literal");
|
556
|
+
}
|
557
|
+
;
|
558
|
+
regex_literal: REGEX_LITERAL {
|
559
|
+
$$ = fy_terminal_node(self, "regex_literal");
|
560
|
+
}
|
561
|
+
;
|
562
|
+
|
563
|
+
hex_literal: HEX_LITERAL {
|
564
|
+
$$ = rb_funcall(self, rb_intern("integer_literal"), 3,
|
565
|
+
INT2NUM(yylineno), rb_str_new2(yytext), INT2NUM(16));
|
566
|
+
}
|
567
|
+
;
|
568
|
+
|
569
|
+
oct_literal: OCT_LITERAL {
|
570
|
+
$$ = rb_funcall(self, rb_intern("integer_literal"), 3,
|
571
|
+
INT2NUM(yylineno), rb_str_new2(yytext), INT2NUM(8));
|
572
|
+
}
|
573
|
+
;
|
574
|
+
|
575
|
+
bin_literal: BIN_LITERAL {
|
576
|
+
$$ = rb_funcall(self, rb_intern("integer_literal"), 3,
|
577
|
+
INT2NUM(yylineno), rb_str_new2(yytext), INT2NUM(2));
|
578
|
+
}
|
579
|
+
;
|
580
|
+
|
581
|
+
literal_value: integer_literal
|
582
|
+
| hex_literal
|
583
|
+
| oct_literal
|
584
|
+
| bin_literal
|
585
|
+
| double_literal
|
586
|
+
| string_literal
|
587
|
+
| symbol_literal
|
588
|
+
| hash_literal
|
589
|
+
| array_literal
|
590
|
+
| regex_literal
|
591
|
+
| block_literal
|
592
|
+
| tuple_literal
|
593
|
+
| range_literal
|
594
|
+
;
|
595
|
+
|
596
|
+
array_literal: empty_array {
|
597
|
+
$$ = $1;
|
598
|
+
}
|
599
|
+
| LBRACKET space exp_comma_list space RBRACKET {
|
600
|
+
$$ = rb_funcall(self, rb_intern("array_literal"), 2, INT2NUM(yylineno), $3);
|
601
|
+
}
|
602
|
+
;
|
603
|
+
|
604
|
+
exp_comma_list: exp {
|
605
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 2, INT2NUM(yylineno), $1);
|
606
|
+
}
|
607
|
+
| exp_comma_list COMMA space exp {
|
608
|
+
$$ = rb_funcall(self, rb_intern("expr_ary"), 3, INT2NUM(yylineno), $4, $1);
|
609
|
+
}
|
610
|
+
| exp_comma_list COMMA {
|
611
|
+
$$ = $1;
|
612
|
+
}
|
613
|
+
;
|
614
|
+
|
615
|
+
empty_array: LBRACKET space RBRACKET {
|
616
|
+
$$ = rb_funcall(self, rb_intern("array_literal"), 1, INT2NUM(yylineno));
|
617
|
+
}
|
618
|
+
;
|
619
|
+
|
620
|
+
hash_literal: LHASH space key_value_list space RHASH {
|
621
|
+
$$ = rb_funcall(self, rb_intern("hash_literal"), 2, INT2NUM(yylineno), $3);
|
622
|
+
}
|
623
|
+
| LHASH space RHASH {
|
624
|
+
$$ = rb_funcall(self, rb_intern("hash_literal"), 1, INT2NUM(yylineno));
|
625
|
+
}
|
626
|
+
;
|
627
|
+
|
628
|
+
block_literal: expression_block {
|
629
|
+
$$ = rb_funcall(self, rb_intern("block_literal"), 3, INT2NUM(yylineno), Qnil, $1);
|
630
|
+
}
|
631
|
+
| STAB block_args STAB space expression_block {
|
632
|
+
$$ = rb_funcall(self, rb_intern("block_literal"), 3, INT2NUM(yylineno), $2, $5);
|
633
|
+
}
|
634
|
+
;
|
635
|
+
|
636
|
+
tuple_literal: LPAREN exp_comma_list RPAREN {
|
637
|
+
$$ = rb_funcall(self, rb_intern("tuple_literal"), 2, INT2NUM(yylineno), $2);
|
638
|
+
}
|
639
|
+
;
|
640
|
+
|
641
|
+
range_literal: LPAREN exp DOT DOT exp RPAREN {
|
642
|
+
$$ = rb_funcall(self, rb_intern("range_literal"), 3, INT2NUM(yylineno), $2, $5);
|
643
|
+
}
|
644
|
+
;
|
645
|
+
|
646
|
+
block_args: block_args_with_comma
|
647
|
+
| block_args_without_comma
|
648
|
+
;
|
649
|
+
|
650
|
+
block_args_without_comma: identifier {
|
651
|
+
$$ = rb_funcall(self, rb_intern("block_args"), 2, INT2NUM(yylineno), $1);
|
652
|
+
}
|
653
|
+
| block_args_without_comma identifier {
|
654
|
+
$$ = rb_funcall(self, rb_intern("block_args"), 3, INT2NUM(yylineno), $2, $1);
|
655
|
+
}
|
656
|
+
;
|
657
|
+
|
658
|
+
block_args_with_comma: identifier {
|
659
|
+
$$ = rb_funcall(self, rb_intern("block_args"), 2, INT2NUM(yylineno), $1);
|
660
|
+
}
|
661
|
+
| block_args_with_comma COMMA identifier {
|
662
|
+
$$ = rb_funcall(self, rb_intern("block_args"), 3, INT2NUM(yylineno), $3, $1);
|
663
|
+
}
|
664
|
+
;
|
665
|
+
|
666
|
+
key_value_list: exp space ARROW space exp {
|
667
|
+
$$ = rb_funcall(self, rb_intern("key_value_list"), 3, INT2NUM(yylineno), $1, $5);
|
668
|
+
}
|
669
|
+
| key_value_list COMMA space exp space ARROW space exp {
|
670
|
+
$$ = rb_funcall(self, rb_intern("key_value_list"), 4, INT2NUM(yylineno), $4, $8, $1);
|
671
|
+
}
|
672
|
+
;
|
673
|
+
|
674
|
+
match_expr: MATCH exp THIN_ARROW LCURLY space match_body space RCURLY {
|
675
|
+
$$ = rb_funcall(self, rb_intern("match_expr"), 3, INT2NUM(yylineno), $2, $6);
|
676
|
+
}
|
677
|
+
;
|
678
|
+
|
679
|
+
match_body: match_clause {
|
680
|
+
$$ = rb_funcall(self, rb_intern("match_body"), 2, INT2NUM(yylineno), $1);
|
681
|
+
}
|
682
|
+
| match_body match_clause {
|
683
|
+
$$ = rb_funcall(self, rb_intern("match_body"), 3, INT2NUM(yylineno), $2, $1);
|
684
|
+
}
|
685
|
+
;
|
686
|
+
|
687
|
+
match_clause: CASE exp THIN_ARROW expression_list {
|
688
|
+
$$ = rb_funcall(self, rb_intern("match_clause"), 3, INT2NUM(yylineno), $2, $4);
|
689
|
+
}
|
690
|
+
| CASE exp THIN_ARROW STAB identifier STAB expression_list {
|
691
|
+
$$ = rb_funcall(self, rb_intern("match_clause"), 4, INT2NUM(yylineno), $2, $7, $5);
|
692
|
+
}
|
693
|
+
;
|
694
|
+
|
695
|
+
%%
|
696
|
+
|
697
|
+
|
698
|
+
VALUE fy_terminal_node(VALUE self, char* method) {
|
699
|
+
return rb_funcall(self, rb_intern(method), 2, INT2NUM(yylineno), rb_str_new2(yytext));
|
700
|
+
}
|
701
|
+
|
702
|
+
VALUE fy_terminal_node_from(VALUE self, char* method, char* text) {
|
703
|
+
return rb_funcall(self, rb_intern(method), 2, INT2NUM(yylineno), rb_str_new2(text));
|
704
|
+
}
|
705
|
+
|
706
|
+
int yyerror(VALUE self, char *s)
|
707
|
+
{
|
708
|
+
rb_funcall(self, rb_intern("parse_error"), 2, INT2NUM(yylineno), rb_str_new2(yytext));
|
709
|
+
return 1;
|
710
|
+
}
|
711
|
+
|