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.
Files changed (242) hide show
  1. data/AUTHORS +7 -0
  2. data/LICENSE +19 -0
  3. data/README +173 -0
  4. data/Rakefile +255 -0
  5. data/bin/fancy +40 -0
  6. data/bin/fdoc +23 -0
  7. data/bin/fyi +22 -0
  8. data/bin/ifancy +46 -0
  9. data/boot/README +12 -0
  10. data/boot/code_loader.rb +165 -0
  11. data/boot/compile.fy +3 -0
  12. data/boot/fancy_ext.rb +13 -0
  13. data/boot/fancy_ext/block_env.rb +29 -0
  14. data/boot/fancy_ext/class.rb +26 -0
  15. data/boot/fancy_ext/kernel.rb +12 -0
  16. data/boot/fancy_ext/module.rb +89 -0
  17. data/boot/fancy_ext/object.rb +34 -0
  18. data/boot/fancy_ext/string_helper.rb +10 -0
  19. data/boot/load.rb +72 -0
  20. data/boot/rbx-compiler/README +12 -0
  21. data/boot/rbx-compiler/compiler.rb +24 -0
  22. data/boot/rbx-compiler/compiler/ast.rb +23 -0
  23. data/boot/rbx-compiler/compiler/ast/README +11 -0
  24. data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
  25. data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
  26. data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
  27. data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
  28. data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
  29. data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
  30. data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
  31. data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
  32. data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
  33. data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
  34. data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
  35. data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
  36. data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
  37. data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
  38. data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
  39. data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
  40. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
  41. data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
  42. data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
  43. data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
  44. data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
  45. data/boot/rbx-compiler/compiler/command.rb +39 -0
  46. data/boot/rbx-compiler/compiler/compiler.rb +83 -0
  47. data/boot/rbx-compiler/compiler/stages.rb +99 -0
  48. data/boot/rbx-compiler/parser.rb +2 -0
  49. data/boot/rbx-compiler/parser/README +15 -0
  50. data/boot/rbx-compiler/parser/Rakefile +54 -0
  51. data/boot/rbx-compiler/parser/extconf.rb +3 -0
  52. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  53. data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
  54. data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
  55. data/boot/rbx-compiler/parser/lexer.lex +180 -0
  56. data/boot/rbx-compiler/parser/parser.rb +356 -0
  57. data/boot/rbx-compiler/parser/parser.y +711 -0
  58. data/boot/rsexp_pretty_printer.rb +76 -0
  59. data/doc/api/fancy.css +93 -0
  60. data/doc/api/fancy.jsonp +1 -0
  61. data/doc/api/fdoc.js +187 -0
  62. data/doc/api/index.html +57 -0
  63. data/doc/api/underscore-min.js +18 -0
  64. data/doc/features.md +228 -0
  65. data/examples/argv.fy +8 -0
  66. data/examples/arithmetic.fy +7 -0
  67. data/examples/armstrong_numbers.fy +33 -0
  68. data/examples/array.fy +52 -0
  69. data/examples/blocks.fy +15 -0
  70. data/examples/boolean.fy +24 -0
  71. data/examples/call_with_receiver.fy +9 -0
  72. data/examples/class.fy +68 -0
  73. data/examples/closures.fy +24 -0
  74. data/examples/constant_access.fy +15 -0
  75. data/examples/default_args.fy +17 -0
  76. data/examples/define_methods.fy +15 -0
  77. data/examples/documentation.fy +57 -0
  78. data/examples/documentation_formatters.fy +25 -0
  79. data/examples/echo.fy +16 -0
  80. data/examples/empty_catch.fy +4 -0
  81. data/examples/exception.fy +9 -0
  82. data/examples/factorial.fy +12 -0
  83. data/examples/fibonacci.fy +16 -0
  84. data/examples/files.fy +23 -0
  85. data/examples/finally.fy +5 -0
  86. data/examples/game_of_life.fy +148 -0
  87. data/examples/hashes.fy +7 -0
  88. data/examples/hello_world.fy +6 -0
  89. data/examples/html_generator.fy +54 -0
  90. data/examples/implicit_return.fy +3 -0
  91. data/examples/matchers.fy +6 -0
  92. data/examples/methods.fy +29 -0
  93. data/examples/nested_classes.fy +27 -0
  94. data/examples/nested_try.fy +9 -0
  95. data/examples/numbers.fy +12 -0
  96. data/examples/pattern_matching.fy +40 -0
  97. data/examples/person.fy +65 -0
  98. data/examples/project-euler/01.fy +8 -0
  99. data/examples/project-euler/02.fy +21 -0
  100. data/examples/project-euler/28.fy +33 -0
  101. data/examples/rbx/and_or.fy +7 -0
  102. data/examples/rbx/blocks.fy +22 -0
  103. data/examples/rbx/classes.fy +32 -0
  104. data/examples/rbx/hello.fy +8 -0
  105. data/examples/rbx/include.fy +12 -0
  106. data/examples/rbx/inherit.fy +11 -0
  107. data/examples/rbx/methods.fy +15 -0
  108. data/examples/rbx/nested_classes.fy +9 -0
  109. data/examples/rbx/require.fy +3 -0
  110. data/examples/rbx/strings.fy +5 -0
  111. data/examples/regex.fy +7 -0
  112. data/examples/require.fy +7 -0
  113. data/examples/retry.fy +12 -0
  114. data/examples/return.fy +13 -0
  115. data/examples/ruby_require.fy +7 -0
  116. data/examples/ruby_send.fy +3 -0
  117. data/examples/singleton_methods.fy +21 -0
  118. data/examples/stupid_quicksort.fy +12 -0
  119. data/examples/threads.fy +18 -0
  120. data/examples/tuple.fy +8 -0
  121. data/examples/webserver/webserver.fy +18 -0
  122. data/lib/argv.fy +36 -0
  123. data/lib/array.fy +207 -0
  124. data/lib/block.fy +88 -0
  125. data/lib/boot.fy +41 -0
  126. data/lib/class.fy +106 -0
  127. data/lib/compiler.fy +14 -0
  128. data/lib/compiler/ast.fy +40 -0
  129. data/lib/compiler/ast/assign.fy +96 -0
  130. data/lib/compiler/ast/block.fy +84 -0
  131. data/lib/compiler/ast/class_def.fy +33 -0
  132. data/lib/compiler/ast/expression_list.fy +47 -0
  133. data/lib/compiler/ast/identifier.fy +113 -0
  134. data/lib/compiler/ast/literals.fy +122 -0
  135. data/lib/compiler/ast/match.fy +88 -0
  136. data/lib/compiler/ast/message_send.fy +110 -0
  137. data/lib/compiler/ast/method_def.fy +90 -0
  138. data/lib/compiler/ast/node.fy +7 -0
  139. data/lib/compiler/ast/range.fy +16 -0
  140. data/lib/compiler/ast/require.fy +15 -0
  141. data/lib/compiler/ast/return.fy +23 -0
  142. data/lib/compiler/ast/script.fy +52 -0
  143. data/lib/compiler/ast/singleton_method_def.fy +35 -0
  144. data/lib/compiler/ast/super.fy +17 -0
  145. data/lib/compiler/ast/try_catch.fy +176 -0
  146. data/lib/compiler/ast/tuple_literal.fy +34 -0
  147. data/lib/compiler/command.fy +51 -0
  148. data/lib/compiler/compiler.fy +73 -0
  149. data/lib/compiler/stages.fy +81 -0
  150. data/lib/directory.fy +17 -0
  151. data/lib/documentation.fy +115 -0
  152. data/lib/enumerable.fy +269 -0
  153. data/lib/eval.fy +31 -0
  154. data/lib/fancy_spec.fy +202 -0
  155. data/lib/fdoc.fy +359 -0
  156. data/lib/fdoc_hook.fy +10 -0
  157. data/lib/file.fy +54 -0
  158. data/lib/hash.fy +56 -0
  159. data/lib/main.fy +80 -0
  160. data/lib/method.fy +22 -0
  161. data/lib/nil_class.fy +56 -0
  162. data/lib/number.fy +87 -0
  163. data/lib/object.fy +170 -0
  164. data/lib/package.fy +61 -0
  165. data/lib/package/dependency.fy +24 -0
  166. data/lib/package/installer.fy +180 -0
  167. data/lib/package/specification.fy +55 -0
  168. data/lib/package/uninstaller.fy +15 -0
  169. data/lib/parser.fy +4 -0
  170. data/lib/parser/ext/README +15 -0
  171. data/lib/parser/ext/ext.c +42 -0
  172. data/lib/parser/ext/ext.h +8 -0
  173. data/lib/parser/ext/extconf.rb +3 -0
  174. data/lib/parser/ext/lexer.lex +187 -0
  175. data/lib/parser/ext/parser.y +744 -0
  176. data/lib/parser/methods.fy +297 -0
  177. data/lib/rbx.fy +37 -0
  178. data/lib/rbx/array.fy +237 -0
  179. data/lib/rbx/bignum.fy +23 -0
  180. data/lib/rbx/block.fy +9 -0
  181. data/lib/rbx/class.fy +129 -0
  182. data/lib/rbx/code_loader.fy +192 -0
  183. data/lib/rbx/console.fy +63 -0
  184. data/lib/rbx/directory.fy +46 -0
  185. data/lib/rbx/documentation.fy +64 -0
  186. data/lib/rbx/environment_variables.fy +3 -0
  187. data/lib/rbx/exception.fy +30 -0
  188. data/lib/rbx/false_class.fy +58 -0
  189. data/lib/rbx/fiber.fy +25 -0
  190. data/lib/rbx/file.fy +191 -0
  191. data/lib/rbx/fixnum.fy +25 -0
  192. data/lib/rbx/float.fy +14 -0
  193. data/lib/rbx/hash.fy +38 -0
  194. data/lib/rbx/integer.fy +15 -0
  195. data/lib/rbx/io.fy +30 -0
  196. data/lib/rbx/match_data.fy +9 -0
  197. data/lib/rbx/method.fy +22 -0
  198. data/lib/rbx/name_error.fy +3 -0
  199. data/lib/rbx/no_method_error.fy +15 -0
  200. data/lib/rbx/object.fy +117 -0
  201. data/lib/rbx/range.fy +15 -0
  202. data/lib/rbx/regexp.fy +9 -0
  203. data/lib/rbx/string.fy +63 -0
  204. data/lib/rbx/symbol.fy +12 -0
  205. data/lib/rbx/system.fy +37 -0
  206. data/lib/rbx/tcp_server.fy +6 -0
  207. data/lib/rbx/tcp_socket.fy +7 -0
  208. data/lib/rbx/thread.fy +75 -0
  209. data/lib/rbx/tuple.fy +37 -0
  210. data/lib/set.fy +61 -0
  211. data/lib/stack.fy +51 -0
  212. data/lib/string.fy +58 -0
  213. data/lib/struct.fy +13 -0
  214. data/lib/symbol.fy +23 -0
  215. data/lib/true_class.fy +43 -0
  216. data/lib/tuple.fy +68 -0
  217. data/lib/version.fy +6 -0
  218. data/tests/argv.fy +13 -0
  219. data/tests/array.fy +343 -0
  220. data/tests/assignment.fy +53 -0
  221. data/tests/block.fy +103 -0
  222. data/tests/class.fy +409 -0
  223. data/tests/control_flow.fy +79 -0
  224. data/tests/documentation.fy +24 -0
  225. data/tests/exception.fy +115 -0
  226. data/tests/file.fy +86 -0
  227. data/tests/hash.fy +101 -0
  228. data/tests/method.fy +131 -0
  229. data/tests/nil_class.fy +55 -0
  230. data/tests/number.fy +128 -0
  231. data/tests/object.fy +125 -0
  232. data/tests/parsing/sexp.fy +50 -0
  233. data/tests/pattern_matching.fy +82 -0
  234. data/tests/range.fy +11 -0
  235. data/tests/set.fy +10 -0
  236. data/tests/stack.fy +22 -0
  237. data/tests/string.fy +102 -0
  238. data/tests/symbol.fy +17 -0
  239. data/tests/true_class.fy +63 -0
  240. data/tests/tuple.fy +21 -0
  241. data/tools/fancy-mode.el +63 -0
  242. 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
+