myco 0.1.0.dev → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -7
- data/LICENSE +1 -1
- data/README.md +79 -0
- data/lib/myco/backtrace.rb +1 -1
- data/lib/myco/bootstrap/component.rb +78 -39
- data/lib/myco/bootstrap/find_constant.rb +12 -1
- data/lib/myco/bootstrap/instance.rb +5 -12
- data/lib/myco/bootstrap/meme.rb +176 -28
- data/lib/myco/bootstrap.my +8 -7
- data/lib/myco/code_loader.rb +332 -0
- data/lib/myco/command/inoculate.my +83 -0
- data/lib/myco/command.my +26 -26
- data/lib/myco/core/BasicDecorators.my +62 -0
- data/lib/myco/core/BasicObject.my +12 -34
- data/lib/myco/core/Decorator.my +1 -0
- data/lib/myco/core/FileToplevel.my +0 -3
- data/lib/myco/core/Myco.my +4 -0
- data/lib/myco/core/Object.my +6 -4
- data/lib/myco/eval.rb +17 -18
- data/lib/myco/misc.rb +16 -0
- data/lib/myco/parser/ast/argument_assembly.rb +76 -0
- data/lib/myco/parser/ast/array_assembly.rb +57 -0
- data/lib/myco/parser/ast/branch_operator.rb +73 -0
- data/lib/myco/parser/ast/constant_access.rb +4 -18
- data/lib/myco/parser/ast/constant_define.rb +3 -3
- data/lib/myco/parser/ast/constant_reopen.rb +12 -13
- data/lib/myco/parser/ast/declare_category.rb +8 -6
- data/lib/myco/parser/ast/declare_decorator.rb +4 -4
- data/lib/myco/parser/ast/declare_file.rb +4 -4
- data/lib/myco/parser/ast/declare_meme.rb +53 -11
- data/lib/myco/parser/ast/declare_object.rb +9 -7
- data/lib/myco/parser/ast/declare_string.rb +5 -5
- data/lib/myco/parser/ast/invoke.rb +18 -36
- data/lib/myco/parser/ast/invoke_method.rb +28 -0
- data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +9 -13
- data/lib/myco/parser/ast/misc.rb +128 -33
- data/lib/myco/parser/ast/myco_module_scope.rb +26 -0
- data/lib/myco/parser/ast/quest.rb +3 -3
- data/lib/myco/parser/ast/to_ruby/array_assembly.rb +15 -0
- data/lib/myco/parser/ast/to_ruby/block.rb +14 -0
- data/lib/myco/parser/ast/to_ruby/block_pass.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/branch_operator.rb +9 -0
- data/lib/myco/parser/ast/to_ruby/constant_access.rb +10 -0
- data/lib/myco/parser/ast/to_ruby/constant_assignment.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/constant_define.rb +9 -0
- data/lib/myco/parser/ast/to_ruby/constant_reopen.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_category.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/declare_decorator.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_file.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_meme.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/declare_object.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/declare_string.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/dynamic_string.rb +14 -0
- data/lib/myco/parser/ast/to_ruby/dynamic_symbol.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/eval_expression.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/false_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/hash_literal.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/invoke.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/invoke_method.rb +35 -0
- data/lib/myco/parser/ast/to_ruby/iter.rb +10 -0
- data/lib/myco/parser/ast/to_ruby/local_variable_access_ambiguous.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/local_variable_assignment.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/myco_module_scope.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/null_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/parameters.rb +60 -0
- data/lib/myco/parser/ast/to_ruby/quest.rb +13 -0
- data/lib/myco/parser/ast/to_ruby/return.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/scoped_constant.rb +11 -0
- data/lib/myco/parser/ast/to_ruby/self.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/splat_value.rb +33 -0
- data/lib/myco/parser/ast/to_ruby/string_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/symbol_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/toplevel_constant.rb +11 -0
- data/lib/myco/parser/ast/to_ruby/true_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/void_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby.rb +138 -0
- data/lib/myco/parser/ast.rb +6 -0
- data/lib/myco/parser/peg_parser.rb +361 -181
- data/lib/myco/parser.rb +27 -11
- data/lib/myco/tools/BasicCommand.my +42 -0
- data/lib/myco/tools/Generator.my +18 -0
- data/lib/myco/toolset.rb +0 -3
- data/lib/myco/version.rb +1 -4
- data/lib/myco.rb +2 -0
- metadata +230 -160
- data/lib/myco/parser/builder.output +0 -3995
- data/lib/myco/parser/builder.racc +0 -585
- data/lib/myco/parser/builder.rb +0 -1592
- data/lib/myco/parser/lexer.rb +0 -2306
- data/lib/myco/parser/lexer.rl +0 -393
- data/lib/myco/parser/lexer_char_classes.rl +0 -56
- data/lib/myco/parser/lexer_common.rb +0 -95
- data/lib/myco/parser/lexer_skeleton.rl +0 -154
- data/lib/myco/parser/peg_parser.kpeg +0 -759
- data/lib/myco/tools/OptionParser.my +0 -38
@@ -1,759 +0,0 @@
|
|
1
|
-
%% name = CodeTools::PegParser
|
2
|
-
#%
|
3
|
-
|
4
|
-
%% { #%
|
5
|
-
attr_accessor :processor
|
6
|
-
attr_accessor :root_node
|
7
|
-
|
8
|
-
# Generate an AST::Node of the given type (generated by the @processor)
|
9
|
-
def node type, locator, *args
|
10
|
-
@processor.send :"process_#{type}", locator.line, *args
|
11
|
-
end
|
12
|
-
|
13
|
-
# Generate a Token with the given type, text, and row_col
|
14
|
-
def token type, text, row_col=nil
|
15
|
-
row_col ||= [current_line, current_column-text.length]
|
16
|
-
Token.new type, text, row_col
|
17
|
-
end
|
18
|
-
|
19
|
-
# A token is a lightweight unit of text with type and location info
|
20
|
-
# as well as some convenience function for common conversion operations.
|
21
|
-
class Token
|
22
|
-
attr_accessor :type
|
23
|
-
attr_accessor :text
|
24
|
-
attr_accessor :line
|
25
|
-
|
26
|
-
def inspect
|
27
|
-
[@type, @text, @line].inspect
|
28
|
-
end
|
29
|
-
alias_method :to_s, :inspect
|
30
|
-
|
31
|
-
def initialize type, text, row_col
|
32
|
-
@type = type
|
33
|
-
@text = text
|
34
|
-
# TODO: integrate columns from location instead of just rows
|
35
|
-
@line = row_col.first
|
36
|
-
end
|
37
|
-
|
38
|
-
def sym; @text.to_sym end
|
39
|
-
def float; Float(@text) end
|
40
|
-
def integer; Integer(@text) end
|
41
|
-
end
|
42
|
-
}
|
43
|
-
|
44
|
-
##
|
45
|
-
# Things to remember about PEG:
|
46
|
-
#
|
47
|
-
# Given the choice (a | b | c),
|
48
|
-
# PEG will consume the first matching choice, not the longest.
|
49
|
-
# There is no ambiguity in PEG because all rule choices are order-dependent.
|
50
|
-
# This means that you should avoid changing the order of choices
|
51
|
-
# in a rule without being mindful of the consequences.
|
52
|
-
#
|
53
|
-
# Given a left-recursive set of rules such as
|
54
|
-
# x = a | b | c
|
55
|
-
# a = x "+" x
|
56
|
-
# PEG will silently ignore the 'a' rule when trying to contruct 'x' and
|
57
|
-
# not even try to pursue it because it would result in infinite recursion.
|
58
|
-
# To avoid left-recursion while retaining left-associativity,
|
59
|
-
# use an iteration rule instead of a recursion rule.
|
60
|
-
# (see the chained_left_atoms rule)
|
61
|
-
|
62
|
-
|
63
|
-
##
|
64
|
-
# Toplevel Terminal Categorizations
|
65
|
-
|
66
|
-
root = declobj_expr_body:n0 { @root_node = node(:declfile, n0, n0) }
|
67
|
-
|
68
|
-
# Declarations
|
69
|
-
decl =
|
70
|
-
declobj
|
71
|
-
| declstr
|
72
|
-
| copen
|
73
|
-
|
74
|
-
# Expressions allowable inside object declarations
|
75
|
-
declobj_expr =
|
76
|
-
category
|
77
|
-
| declobj_expr_not_category
|
78
|
-
|
79
|
-
# Expressions allowable inside object declarations that is not a category
|
80
|
-
declobj_expr_not_category =
|
81
|
-
decl
|
82
|
-
| cdefn
|
83
|
-
| cmeme
|
84
|
-
| constant
|
85
|
-
| meme
|
86
|
-
|
87
|
-
# Expressions allowable inside memes
|
88
|
-
meme_expr =
|
89
|
-
return_arg_expr
|
90
|
-
| arg_expr
|
91
|
-
|
92
|
-
# Expressions allowable as function arguments
|
93
|
-
arg_expr =
|
94
|
-
assignment
|
95
|
-
| left_chained_atoms
|
96
|
-
| dyn_string
|
97
|
-
| dyn_symstr
|
98
|
-
| expr_atom
|
99
|
-
|
100
|
-
# TODO: make expr_atom not redundant with below rules
|
101
|
-
# Expression atoms
|
102
|
-
expr_atom =
|
103
|
-
decl
|
104
|
-
| left_chained_invocations
|
105
|
-
| lit_string
|
106
|
-
| lit_symstr
|
107
|
-
| unary_operation
|
108
|
-
| paren_expr
|
109
|
-
| constant
|
110
|
-
| lit_simple
|
111
|
-
| lit_array
|
112
|
-
| invoke
|
113
|
-
|
114
|
-
# Expression atoms that are not invocation chains
|
115
|
-
expr_atom_not_chained =
|
116
|
-
decl
|
117
|
-
| lit_string
|
118
|
-
| lit_symstr
|
119
|
-
| unary_operation
|
120
|
-
| paren_expr
|
121
|
-
| constant
|
122
|
-
| lit_simple
|
123
|
-
| lit_array
|
124
|
-
| invoke
|
125
|
-
|
126
|
-
# Expression atoms that are not strings
|
127
|
-
expr_atom_not_string =
|
128
|
-
decl
|
129
|
-
| left_chained_invocations
|
130
|
-
| unary_operation
|
131
|
-
| paren_expr
|
132
|
-
| constant
|
133
|
-
| lit_simple
|
134
|
-
| lit_array
|
135
|
-
| invoke
|
136
|
-
|
137
|
-
|
138
|
-
##
|
139
|
-
# Character Classes
|
140
|
-
|
141
|
-
eol_comment = '#' (!c_eol .)*
|
142
|
-
|
143
|
-
c_nl = "\n"
|
144
|
-
c_spc = /[ \t\r\f\v]/ | "\\\n" | eol_comment
|
145
|
-
c_spc_nl = c_spc | c_nl
|
146
|
-
|
147
|
-
c_eof = !.
|
148
|
-
c_eol = c_nl | c_eof
|
149
|
-
c_any = .
|
150
|
-
|
151
|
-
c_upper = /[[:upper:]]/
|
152
|
-
c_lower = /[[:lower:]]/ | "_"
|
153
|
-
c_num = /[0-9]/
|
154
|
-
c_alpha = c_lower | c_upper
|
155
|
-
c_alnum = c_alpha | c_num
|
156
|
-
c_suffix = '!' | '?'
|
157
|
-
|
158
|
-
|
159
|
-
##
|
160
|
-
# Tokens
|
161
|
-
|
162
|
-
t_CONST_SEP = < ',' > ~token(:t_CONST_SEP, text)
|
163
|
-
t_EXPR_SEP = < ';' | c_nl > ~token(:t_EXPR_SEP, text)
|
164
|
-
t_ARG_SEP = < ',' | c_nl > ~token(:t_ARG_SEP, text)
|
165
|
-
t_DECLARE_BEGIN = < '{' > ~token(:t_DECLARE_BEGIN, text)
|
166
|
-
t_DECLARE_END = < '}' | c_eof > ~token(:t_DECLARE_END, text)
|
167
|
-
t_MEME_MARK = < ':' > ~token(:t_MEME_MARK, text)
|
168
|
-
t_MEME_BEGIN = < '{' > ~token(:t_MEME_BEGIN, text)
|
169
|
-
t_MEME_END = < '}' > ~token(:t_MEME_END, text)
|
170
|
-
t_PAREN_BEGIN = < '(' > ~token(:t_PAREN_BEGIN, text)
|
171
|
-
t_PAREN_END = < ')' > ~token(:t_PAREN_END, text)
|
172
|
-
t_DEFINE = < '<' > ~token(:t_DEFINE, text)
|
173
|
-
t_REOPEN = < '<<' > ~token(:t_REOPEN, text)
|
174
|
-
t_PARAMS_BEGIN = < '|' > ~token(:t_PARAMS_BEGIN, text)
|
175
|
-
t_PARAMS_END = < '|' > ~token(:t_PARAMS_END, text)
|
176
|
-
t_ARGS_BEGIN = < '(' > ~token(:t_ARGS_BEGIN, text)
|
177
|
-
t_ARGS_END = < ')' > ~token(:t_ARGS_END, text)
|
178
|
-
t_ARRAY_BEGIN = < '[' > ~token(:t_ARRAY_BEGIN, text)
|
179
|
-
t_ARRAY_END = < ']' > ~token(:t_ARRAY_END, text)
|
180
|
-
|
181
|
-
t_CONSTANT = < (c_upper c_alnum*) > ~token(:t_CONSTANT, text)
|
182
|
-
t_IDENTIFIER = < (c_lower c_alnum*) c_suffix? >
|
183
|
-
~token(:t_IDENTIFIER, text)
|
184
|
-
t_SYMBOL = ':' < (c_lower c_alnum*) > ~token(:t_SYMBOL, text)
|
185
|
-
|
186
|
-
t_NULL = < 'null' > ~token(:t_NULL, text)
|
187
|
-
t_VOID = < 'void' > ~token(:t_VOID, text)
|
188
|
-
t_TRUE = < 'true' > ~token(:t_TRUE, text)
|
189
|
-
t_FALSE = < 'false' > ~token(:t_FALSE, text)
|
190
|
-
t_SELF = < 'self' > ~token(:t_SELF, text)
|
191
|
-
t_FLOAT = < c_num+ '.' c_num+ > ~token(:t_FLOAT, text)
|
192
|
-
t_INTEGER = < c_num+ > ~token(:t_INTEGER, text)
|
193
|
-
|
194
|
-
t_JUMP = < '->' > ~token(:t_JUMP, text)
|
195
|
-
t_DOT = < '.' > ~token(:t_DOT, text)
|
196
|
-
t_QUEST = < '.' c_spc_nl* '?' > ~token(:t_QUEST, text)
|
197
|
-
t_SCOPE = < '::' > ~token(:t_SCOPE, text)
|
198
|
-
t_ASSIGN = < '=' > ~token(:t_ASSIGN, text)
|
199
|
-
t_OP_TOPROC = < '&' > ~token(:t_OP_TOPROC, text)
|
200
|
-
t_OP_NOT = < '!' > ~token(:t_OP_NOT, text)
|
201
|
-
t_OP_PLUS = < '+' > ~token(:t_OP_PLUS, text)
|
202
|
-
t_OP_MINUS = < '-' > ~token(:t_OP_MINUS, text)
|
203
|
-
t_OP_MULT = < '*' > ~token(:t_OP_MULT, text)
|
204
|
-
t_OP_DIV = < '/' > ~token(:t_OP_DIV, text)
|
205
|
-
t_OP_MOD = < '%' > ~token(:t_OP_MOD, text)
|
206
|
-
t_OP_EXP = < '**' > ~token(:t_OP_EXP, text)
|
207
|
-
t_OP_AND = < '&&' > ~token(:t_OP_AND, text)
|
208
|
-
t_OP_OR = < '||' > ~token(:t_OP_OR, text)
|
209
|
-
t_OP_COMPARE = < ('<=>'|'=~'|'=='|'<='|'>='|'<'|'>') >
|
210
|
-
~token(:t_OP_COMPARE, text)
|
211
|
-
|
212
|
-
string_norm = /[^\\\"]/
|
213
|
-
t_STRING_BODY = < string_norm* ("\\" c_any string_norm*)* >
|
214
|
-
~token(:t_STRING_BODY, text)
|
215
|
-
t_STRING_BEGIN = < '"' > ~token(:t_STRING_BEGIN, text)
|
216
|
-
t_STRING_END = < '"' > ~token(:t_STRING_END, text)
|
217
|
-
t_SYMSTR_BEGIN = < ':"' > ~token(:t_SYMSTR_BEGIN, text)
|
218
|
-
|
219
|
-
sstring_norm = /[^\\\']/
|
220
|
-
t_SSTRING_BODY = < sstring_norm* ("\\" c_any sstring_norm*)* >
|
221
|
-
~token(:t_SSTRING_BODY, text)
|
222
|
-
t_SSTRING_BEGIN = < "'" > ~token(:t_SSTRING_BEGIN, text)
|
223
|
-
t_SSTRING_END = < "'" > ~token(:t_SSTRING_END, text)
|
224
|
-
|
225
|
-
catgry_norm = /[^\\\[\]]/
|
226
|
-
t_CATGRY_BODY = < catgry_norm* ("\\" c_any catgry_norm*)* >
|
227
|
-
~token(:t_CATGRY_BODY, text)
|
228
|
-
t_CATGRY_BEGIN = < '[' > ~token(:t_CATGRY_BEGIN, text)
|
229
|
-
t_CATGRY_END = < ']' > ~token(:t_CATGRY_END, text)
|
230
|
-
|
231
|
-
|
232
|
-
##
|
233
|
-
# Simple literals
|
234
|
-
|
235
|
-
lit_simple =
|
236
|
-
t_NULL:t0 ~node(:null, t0)
|
237
|
-
| t_VOID:t0 ~node(:void, t0)
|
238
|
-
| t_TRUE:t0 ~node(:true, t0)
|
239
|
-
| t_FALSE:t0 ~node(:false, t0)
|
240
|
-
| t_SELF:t0 ~node(:self, t0)
|
241
|
-
| t_FLOAT:t0 ~node(:lit, t0, t0.float)
|
242
|
-
| t_INTEGER:t0 ~node(:lit, t0, t0.integer)
|
243
|
-
| t_SYMBOL:t0 ~node(:lit, t0, t0.sym)
|
244
|
-
|
245
|
-
##
|
246
|
-
# Enclosed literals
|
247
|
-
|
248
|
-
lit_string =
|
249
|
-
t_STRING_BEGIN t_STRING_BODY:tb t_STRING_END
|
250
|
-
~node(:lit, tb, encode_escapes(tb.text))
|
251
|
-
| t_SSTRING_BEGIN t_SSTRING_BODY:tb t_SSTRING_END
|
252
|
-
~node(:lit, tb, encode_escapes(tb.text))
|
253
|
-
|
254
|
-
lit_string_as_symbol = # Used in contexts where a bare string is a symbol
|
255
|
-
t_STRING_BEGIN t_STRING_BODY:tb t_STRING_END
|
256
|
-
~node(:lit, tb, encode_escapes(tb.text).to_sym)
|
257
|
-
| t_SSTRING_BEGIN t_SSTRING_BODY:tb t_SSTRING_END
|
258
|
-
~node(:lit, tb, encode_escapes(tb.text).to_sym)
|
259
|
-
|
260
|
-
lit_symstr =
|
261
|
-
t_SYMSTR_BEGIN t_STRING_BODY:tb t_STRING_END
|
262
|
-
~node(:lit, tb, encode_escapes(tb.text).to_sym)
|
263
|
-
|
264
|
-
category_name = # Used only in declobj body
|
265
|
-
t_CATGRY_BEGIN t_CATGRY_BODY:tb t_CATGRY_END
|
266
|
-
~node(:lit, tb, encode_escapes(tb.text).to_sym)
|
267
|
-
|
268
|
-
##
|
269
|
-
# String interpolations / juxtapositions
|
270
|
-
|
271
|
-
expr_atom_evstr =
|
272
|
-
expr_atom_not_string:n0
|
273
|
-
~node(:evstr, n0, n0)
|
274
|
-
|
275
|
-
dyn_string_parts =
|
276
|
-
(c_spc* expr_atom_evstr:n0 c_spc* lit_string:n1 {[n0,n1]})+:nlist
|
277
|
-
{ nlist.flatten }
|
278
|
-
|
279
|
-
dyn_string =
|
280
|
-
lit_string:n0 dyn_string_parts:nrest
|
281
|
-
~node(:dstr, n0, n0.value, nrest)
|
282
|
-
|
283
|
-
dyn_symstr =
|
284
|
-
lit_symstr:n0 dyn_string_parts:nrest
|
285
|
-
~node(:dsym, n0, n0.value.to_s, nrest)
|
286
|
-
|
287
|
-
##
|
288
|
-
# Constants
|
289
|
-
|
290
|
-
constant =
|
291
|
-
constant:n0 t_SCOPE:ts t_CONSTANT:tc ~node(:colon2, ts, n0, tc.sym)
|
292
|
-
| t_SCOPE:ts t_CONSTANT:tc ~node(:colon3, ts, tc.sym)
|
293
|
-
| t_CONSTANT:tc ~node(:const, tc, tc.sym)
|
294
|
-
|
295
|
-
const_sep = (c_spc_nl* t_CONST_SEP c_spc_nl*)+
|
296
|
-
|
297
|
-
constant_list =
|
298
|
-
constant:n0 (const_sep constant:n)*:nrest
|
299
|
-
~node(:array, n0, [n0, *nrest])
|
300
|
-
|
301
|
-
##
|
302
|
-
# Bare identifiers
|
303
|
-
|
304
|
-
# Used in contexts where a bare identifier is a symbol
|
305
|
-
id_as_symbol = t_IDENTIFIER:t0 ~node(:lit, t0, t0.sym)
|
306
|
-
|
307
|
-
##
|
308
|
-
# Object declarations
|
309
|
-
|
310
|
-
declobj_sepd_exprs =
|
311
|
-
declobj_expr:n0 (arg_sep declobj_expr:n)*:nrest arg_sep_opt { [n0, *nrest] }
|
312
|
-
|
313
|
-
declobj_expr_body =
|
314
|
-
arg_sep_opt declobj_sepd_exprs:nlist t_DECLARE_END:te
|
315
|
-
~node(:block, nlist.first, nlist)
|
316
|
-
| arg_sep_opt t_DECLARE_END:te
|
317
|
-
~node(:null, te)
|
318
|
-
|
319
|
-
declobj =
|
320
|
-
constant_list:n0 c_spc_nl* t_DECLARE_BEGIN:t declobj_expr_body:n1
|
321
|
-
~node(:declobj, t, n0, n1)
|
322
|
-
|
323
|
-
category_expr =
|
324
|
-
declobj_expr_not_category
|
325
|
-
|
326
|
-
category_sepd_exprs =
|
327
|
-
category_expr:n0 (arg_sep category_expr:n)*:nrest { [n0, *nrest] }
|
328
|
-
|
329
|
-
category =
|
330
|
-
category_name:n0 arg_sep category_sepd_exprs?:nlist &(arg_sep_opt (t_CATGRY_BEGIN | t_DECLARE_END))
|
331
|
-
~node(:category, n0, n0,
|
332
|
-
(nlist ? node(:block, nlist.first, nlist) : node(:null, n0)))
|
333
|
-
|
334
|
-
copen =
|
335
|
-
constant:n0 c_spc_nl* t_REOPEN:tb c_spc_nl* t_DECLARE_BEGIN declobj_expr_body:n1
|
336
|
-
~node(:copen, tb, n0, n1)
|
337
|
-
|
338
|
-
cdefn =
|
339
|
-
constant:n0 c_spc_nl* t_DEFINE:t c_spc_nl* declobj:n1
|
340
|
-
~node(:cdefn, t, n0, n1)
|
341
|
-
|
342
|
-
##
|
343
|
-
# String object declarations
|
344
|
-
|
345
|
-
t_DECLSTR_BEGIN =
|
346
|
-
< /[^\s{:,<][^\s]+/ >
|
347
|
-
{
|
348
|
-
|
349
|
-
# Table of replacement characters to use when calculating
|
350
|
-
# the ending delimiter from the starting delimiter.
|
351
|
-
# Directional characters are replaced with their opposite.
|
352
|
-
@declstr_replace_tbl ||= %w{
|
353
|
-
< > ( ) { } [ ]
|
354
|
-
}
|
355
|
-
|
356
|
-
# Calculate the ending delimiter to look for and store it
|
357
|
-
@declstr_destrlim = text \
|
358
|
-
.split(/(?<=[^a-zA-Z])|(?=[^a-zA-Z])/)
|
359
|
-
.map { |str|
|
360
|
-
idx = @declstr_replace_tbl.find_index(str)
|
361
|
-
idx.nil? ? str :
|
362
|
-
(idx.odd? ? @declstr_replace_tbl[idx-1] : @declstr_replace_tbl[idx+1])
|
363
|
-
}
|
364
|
-
.reverse
|
365
|
-
.join ''
|
366
|
-
|
367
|
-
token(:t_DECLSTR_BEGIN, text)
|
368
|
-
}
|
369
|
-
|
370
|
-
t_DECLSTR_END =
|
371
|
-
c_spc_nl* < (< /\S+/ > &{text == @declstr_destrlim}) >
|
372
|
-
~token(:t_DECLSTR_END, text)
|
373
|
-
|
374
|
-
s_DECLSTR_BODYLINE =
|
375
|
-
< /[^\n]*\n/ >
|
376
|
-
&{ text =~ /^(\s*)(\S+)/; $2!=@declstr_destrlim }
|
377
|
-
{ text }
|
378
|
-
|
379
|
-
s_DECLSTR_BODY =
|
380
|
-
s_DECLSTR_BODYLINE*:slist
|
381
|
-
{ slist[1..-1].join('') }
|
382
|
-
|
383
|
-
declstr_body =
|
384
|
-
t_DECLSTR_BEGIN:tb s_DECLSTR_BODY:st c_spc_nl* t_DECLSTR_END
|
385
|
-
~node(:str, tb, st)
|
386
|
-
|
387
|
-
declstr =
|
388
|
-
constant_list:nc c_spc+ declstr_body:nb
|
389
|
-
~node(:declstr, nc, nc, nb)
|
390
|
-
|
391
|
-
##
|
392
|
-
# Jumps
|
393
|
-
|
394
|
-
return_arg_expr =
|
395
|
-
arg_expr:n0 c_spc* t_JUMP:to
|
396
|
-
~node(:return, to, n0)
|
397
|
-
|
398
|
-
##
|
399
|
-
# Assignment
|
400
|
-
|
401
|
-
assignment =
|
402
|
-
local_assignment
|
403
|
-
| invoke_assignment
|
404
|
-
|
405
|
-
assign_rhs =
|
406
|
-
arg_expr
|
407
|
-
|
408
|
-
local_assignment =
|
409
|
-
t_IDENTIFIER:ti c_spc_nl* t_ASSIGN:to c_spc_nl* assign_rhs:rhs
|
410
|
-
~node(:lasgn, to, ti.sym, rhs)
|
411
|
-
|
412
|
-
invoke_assignment_lhs =
|
413
|
-
left_chained_invocations
|
414
|
-
| invoke
|
415
|
-
|
416
|
-
invoke_assignment =
|
417
|
-
invoke_assignment_lhs:lhs c_spc_nl* t_ASSIGN:to c_spc_nl* assign_rhs:rhs
|
418
|
-
{
|
419
|
-
lhs.name = :"#{lhs.name}="
|
420
|
-
orig_arguments = lhs.arguments && lhs.arguments.body || []
|
421
|
-
lhs.arguments = node(:array, rhs, [rhs, *orig_arguments])
|
422
|
-
lhs
|
423
|
-
}
|
424
|
-
|
425
|
-
|
426
|
-
##
|
427
|
-
# Invoke - Results in a :lambig, :call, or :iter with a :call within
|
428
|
-
|
429
|
-
invoke_body =
|
430
|
-
(c_spc_nl* param_list:n)?:np c_spc_nl* meme_enclosed_expr_body:nb
|
431
|
-
{ [np, nb] }
|
432
|
-
|
433
|
-
invoke =
|
434
|
-
t_IDENTIFIER:tn (c_spc_nl* arg_list:na)?:na (c_spc_nl* invoke_body:n)?:nlist
|
435
|
-
~node(:invoke, tn, nil, tn.sym, na, *nlist)
|
436
|
-
|
437
|
-
op_invoke = # Allow some binary operators to be invoked with a dot
|
438
|
-
op_invoke_id:tn (c_spc_nl* arg_list:na)?:na (c_spc_nl* invoke_body:n)?:nlist
|
439
|
-
~node(:invoke, tn, nil, tn.sym, na, *nlist)
|
440
|
-
|
441
|
-
op_invoke_id =
|
442
|
-
left_op
|
443
|
-
|
444
|
-
##
|
445
|
-
# Argument lists
|
446
|
-
|
447
|
-
arg_sep = (c_spc* t_ARG_SEP c_spc*)+
|
448
|
-
arg_sep_opt = (c_spc | t_ARG_SEP)*
|
449
|
-
|
450
|
-
in_arg_normal =
|
451
|
-
in_arg_splat
|
452
|
-
| arg_expr:n0 !in_arg_kwarg_mark { n0 }
|
453
|
-
|
454
|
-
in_arg_normals =
|
455
|
-
in_arg_normal:n0 (arg_sep in_arg_normal:n)*:nrest
|
456
|
-
{ [n0,*nrest] }
|
457
|
-
|
458
|
-
in_arg_kwargs =
|
459
|
-
in_arg_kwarg:n0 (arg_sep in_arg_kwarg:n)*:nrest
|
460
|
-
~node(:hash, n0.first, [n0,*nrest].flatten)
|
461
|
-
|
462
|
-
in_arg_kwarg_mark = c_spc_nl* t_MEME_MARK:to
|
463
|
-
in_arg_kwarg =
|
464
|
-
id_as_symbol:n0 in_arg_kwarg_mark c_spc_nl* arg_expr:n1
|
465
|
-
{ [n0, n1] }
|
466
|
-
|
467
|
-
in_arg_splat =
|
468
|
-
t_OP_MULT:to expr_atom:n0
|
469
|
-
~node(:splat, to, n0)
|
470
|
-
|
471
|
-
in_arg_block =
|
472
|
-
t_OP_TOPROC:to expr_atom:n0
|
473
|
-
~node(:block_pass, to, nil, n0)
|
474
|
-
|
475
|
-
in_arg_list =
|
476
|
-
in_arg_normals:n0 arg_sep in_arg_kwargs:n1 arg_sep in_arg_block:n2 { [*n0,n1,n2] }
|
477
|
-
| in_arg_normals:n0 arg_sep in_arg_kwargs:n1 { [*n0,n1] }
|
478
|
-
| in_arg_normals:n0 arg_sep in_arg_block:n1 { [*n0,n1] }
|
479
|
-
| in_arg_kwargs:n0 arg_sep in_arg_block:n1 { [n0, n1] }
|
480
|
-
| in_arg_normals:n0 { [*n0] }
|
481
|
-
| in_arg_kwargs:n0 { [n0] }
|
482
|
-
| in_arg_block:n0 { [n0] }
|
483
|
-
|
484
|
-
arg_list =
|
485
|
-
t_ARGS_BEGIN:tb arg_sep_opt t_ARGS_END
|
486
|
-
~args_assemble(tb, node(:array, tb, []))
|
487
|
-
| t_ARGS_BEGIN:tb arg_sep_opt in_arg_list:nlist arg_sep_opt t_ARGS_END
|
488
|
-
~args_assemble(tb, node(:array, tb, nlist))
|
489
|
-
|
490
|
-
lit_array =
|
491
|
-
t_ARRAY_BEGIN:tb arg_sep_opt t_ARRAY_END
|
492
|
-
~args_assemble(tb, node(:array, tb, []))
|
493
|
-
| t_ARRAY_BEGIN:tb arg_sep_opt in_arg_list:nlist arg_sep_opt t_ARRAY_END
|
494
|
-
~args_assemble(tb, node(:array, tb, nlist))
|
495
|
-
|
496
|
-
##
|
497
|
-
# Parameter lists
|
498
|
-
|
499
|
-
param =
|
500
|
-
t_IDENTIFIER:ti c_spc_nl* t_ASSIGN:to c_spc_nl* arg_expr:nv
|
501
|
-
{ [:optional, node(:lasgn, ti, ti.sym, nv)] }
|
502
|
-
| t_IDENTIFIER:ti c_spc_nl* t_MEME_MARK:to c_spc_nl* arg_expr?:nv
|
503
|
-
{ [:kwargs, node(:lasgn, ti, ti.sym, (nv || node(:lit, to, :*)))] }
|
504
|
-
| t_OP_EXP c_spc_nl* t_IDENTIFIER:ti { [:kwrest, ti.sym] }
|
505
|
-
| t_OP_MULT c_spc_nl* t_IDENTIFIER:ti { [:rest, ti.sym] }
|
506
|
-
| t_OP_TOPROC c_spc_nl* t_IDENTIFIER:ti { [:block, ti.sym] }
|
507
|
-
| t_IDENTIFIER:ti { [:required, ti.sym] }
|
508
|
-
|
509
|
-
param_sepd =
|
510
|
-
arg_sep param:n0 { n0 }
|
511
|
-
|
512
|
-
param_sepds =
|
513
|
-
param:n0 (arg_sep param:n)*:nrest arg_sep_opt { [n0, *nrest] }
|
514
|
-
|
515
|
-
param_list =
|
516
|
-
t_PARAMS_BEGIN:tb t_PARAMS_END
|
517
|
-
{ node(:args, tb, nil, nil, nil, nil, nil, nil, nil) }
|
518
|
-
| t_PARAMS_BEGIN:tb param_sepds:plist t_PARAMS_END
|
519
|
-
{
|
520
|
-
required, optional, rest, kwargs, kwrest, block = 6.times.map { [] }
|
521
|
-
|
522
|
-
required << plist.shift[1] while plist[0] && plist[0][0] == :required
|
523
|
-
optional << plist.shift[1] while plist[0] && plist[0][0] == :optional
|
524
|
-
rest << plist.shift[1] while plist[0] && plist[0][0] == :rest
|
525
|
-
kwargs << plist.shift[1] while plist[0] && plist[0][0] == :kwargs
|
526
|
-
kwrest << plist.shift[1] while plist[0] && plist[0][0] == :kwrest
|
527
|
-
block << plist.shift[1] while plist[0] && plist[0][0] == :block
|
528
|
-
|
529
|
-
required = required
|
530
|
-
optional = optional.empty? ? nil : node(:block, tb, optional)
|
531
|
-
rest = rest.first
|
532
|
-
post = nil
|
533
|
-
kwargs = kwargs.empty? ? nil : node(:block, tb, kwargs)
|
534
|
-
kwrest = kwrest.first
|
535
|
-
block = block.first
|
536
|
-
|
537
|
-
node(:args, tb, required, optional, rest, post, kwargs, kwrest, block)
|
538
|
-
}
|
539
|
-
|
540
|
-
##
|
541
|
-
# Two-term operators
|
542
|
-
|
543
|
-
left_op =
|
544
|
-
t_OP_EXP
|
545
|
-
| t_OP_MULT | t_OP_DIV | t_OP_MOD
|
546
|
-
| t_OP_PLUS | t_OP_MINUS
|
547
|
-
| t_OP_COMPARE
|
548
|
-
| t_OP_AND | t_OP_OR
|
549
|
-
|
550
|
-
# Achieve left-associativity through iteration.
|
551
|
-
#
|
552
|
-
# PEG parsers get tripped up by left recursion
|
553
|
-
# (in contrast to LALR parsers, which prefer left recursion).
|
554
|
-
# This is a well-understood limitation, but refer to:
|
555
|
-
# http://www.dalnefre.com/wp/2011/05/parsing-expression-grammars-part-4/
|
556
|
-
# for an easy-to-understand explanation of this problem and this solution.
|
557
|
-
#
|
558
|
-
left_chained_atoms =
|
559
|
-
expr_atom:n0 (c_spc_nl* left_op:to c_spc_nl* expr_atom:n1 { [to, n1] })+:list
|
560
|
-
{
|
561
|
-
list.unshift n0
|
562
|
-
list.flatten!
|
563
|
-
|
564
|
-
collapse(list, :t_OP_EXP)
|
565
|
-
collapse(list, :t_OP_MULT, :t_OP_DIV, :t_OP_MOD)
|
566
|
-
collapse(list, :t_OP_PLUS, :t_OP_MINUS)
|
567
|
-
collapse(list, :t_OP_COMPARE)
|
568
|
-
collapse(list, :t_OP_AND, :t_OP_OR) do |n0,op,n1|
|
569
|
-
type = { :t_OP_AND=>:and, :t_OP_OR=>:or }[op.type]
|
570
|
-
node(type, op, n0, n1)
|
571
|
-
end
|
572
|
-
|
573
|
-
# There should only be one resulting node left
|
574
|
-
raise "Failed to fully collapse left_chained_atoms: #{list}" \
|
575
|
-
unless list.count == 1
|
576
|
-
|
577
|
-
list.first
|
578
|
-
}
|
579
|
-
|
580
|
-
##
|
581
|
-
# Invocations and Quests (soft-failing invocations)
|
582
|
-
|
583
|
-
left_invoke_op =
|
584
|
-
t_QUEST
|
585
|
-
| t_DOT
|
586
|
-
|
587
|
-
# Achieve left-associativity through iteration.
|
588
|
-
# (see left_chained_atoms).
|
589
|
-
#
|
590
|
-
left_chained_invocations =
|
591
|
-
expr_atom_not_chained:n0 (c_spc_nl* left_invoke_op:to c_spc_nl* (invoke | op_invoke):n1 { [to, n1] })+:list
|
592
|
-
{
|
593
|
-
list.unshift n0
|
594
|
-
list.flatten!
|
595
|
-
|
596
|
-
collapse(list, :t_DOT, :t_QUEST) do |n0,op,n1|
|
597
|
-
op.type==:t_DOT ? (n1.receiver=n0; n1) : node(:quest, op, n0, n1)
|
598
|
-
end
|
599
|
-
|
600
|
-
# There should only be one resulting node left
|
601
|
-
raise "Failed to fully collapse left_chained_invocations: #{list}" \
|
602
|
-
unless list.count == 1
|
603
|
-
|
604
|
-
list.first
|
605
|
-
}
|
606
|
-
|
607
|
-
##
|
608
|
-
# Unary operators
|
609
|
-
|
610
|
-
unary_operation =
|
611
|
-
t_OP_NOT:to expr_atom:n0
|
612
|
-
~node(:call, to, n0, :"!", nil)
|
613
|
-
|
614
|
-
##
|
615
|
-
# Memes and etc..
|
616
|
-
|
617
|
-
t_inln_sep = !t_ARG_SEP t_EXPR_SEP
|
618
|
-
|
619
|
-
inln_sep = (c_spc* t_inln_sep c_spc*)+
|
620
|
-
inln_sep_opt = (c_spc | t_inln_sep)*
|
621
|
-
|
622
|
-
expr_sep = (c_spc* t_EXPR_SEP c_spc*)+
|
623
|
-
expr_sep_opt = (c_spc | t_EXPR_SEP)*
|
624
|
-
|
625
|
-
meme_inline_sepd_exprs =
|
626
|
-
meme_expr:n0 (inln_sep meme_expr:n)*:nrest inln_sep_opt { [n0, *nrest] }
|
627
|
-
|
628
|
-
meme_sepd_exprs =
|
629
|
-
meme_expr:n0 (expr_sep meme_expr:n)*:nrest expr_sep_opt { [n0, *nrest] }
|
630
|
-
|
631
|
-
meme_inline_expr_body =
|
632
|
-
inln_sep_opt meme_inline_sepd_exprs:nlist
|
633
|
-
~node(:block, nlist.first, nlist)
|
634
|
-
|
635
|
-
meme_expr_body =
|
636
|
-
expr_sep_opt meme_sepd_exprs:nlist t_MEME_END:te
|
637
|
-
~node(:block, nlist.first, nlist)
|
638
|
-
| expr_sep_opt t_MEME_END:te
|
639
|
-
~node(:null, te)
|
640
|
-
|
641
|
-
paren_expr_body =
|
642
|
-
expr_sep_opt meme_sepd_exprs:nlist t_PAREN_END:te
|
643
|
-
{ nlist.count==1 ? nlist.first : node(:block, nlist.first, nlist) }
|
644
|
-
| expr_sep_opt t_PAREN_END:te
|
645
|
-
~node(:null, te)
|
646
|
-
|
647
|
-
paren_expr =
|
648
|
-
t_PAREN_BEGIN paren_expr_body:n0 { n0 }
|
649
|
-
|
650
|
-
meme_enclosed_expr_body =
|
651
|
-
t_MEME_BEGIN meme_expr_body:n0 { n0 }
|
652
|
-
|
653
|
-
meme_either_body =
|
654
|
-
meme_enclosed_expr_body
|
655
|
-
| meme_inline_expr_body
|
656
|
-
|
657
|
-
cmeme =
|
658
|
-
constant:n0 c_spc* t_MEME_MARK:tm c_spc_nl* meme_inline_expr_body:n1
|
659
|
-
~node(:cdecl, tm, n0, n1)
|
660
|
-
|
661
|
-
meme_name =
|
662
|
-
id_as_symbol
|
663
|
-
| lit_string_as_symbol
|
664
|
-
|
665
|
-
decorator =
|
666
|
-
meme_name:ni arg_list?:na
|
667
|
-
~node(:deco, ni, ni, na)
|
668
|
-
|
669
|
-
decorators_and_meme_name =
|
670
|
-
decorator:n0 (c_spc* decorator:n)*:nrest
|
671
|
-
~node(:array, n0, [n0, *nrest].reverse)
|
672
|
-
|
673
|
-
meme =
|
674
|
-
decorators_and_meme_name:nd c_spc* t_MEME_MARK:tm (c_spc_nl* param_list:n)?:np c_spc_nl* meme_either_body:nb
|
675
|
-
~node(:meme, tm, nd.body.shift.name, nd, np, nb)
|
676
|
-
| decorators_and_meme_name:nd
|
677
|
-
~node(:meme, tm, nd.body.shift.name, nd, nil, nil)
|
678
|
-
|
679
|
-
|
680
|
-
%% {
|
681
|
-
#%
|
682
|
-
# Encode escape characters in string literals
|
683
|
-
# TODO: rigorously test and refine
|
684
|
-
#
|
685
|
-
def encode_escapes str
|
686
|
-
str.gsub /\\(.)/ do "#{$1}" end
|
687
|
-
end
|
688
|
-
|
689
|
-
# Given a node,op list ([node, op, node, op, ... node]) and operator types,
|
690
|
-
# collapse the (node, op, node) groups where the operator is one of the types
|
691
|
-
#
|
692
|
-
# This function is meant to be called several times on the same list,
|
693
|
-
# with a different set of operator types each time, in order of precedence.
|
694
|
-
#
|
695
|
-
def collapse input, *types
|
696
|
-
output = []
|
697
|
-
|
698
|
-
# Scan through, reducing or shifting based on the operator
|
699
|
-
while input.count > 2
|
700
|
-
n0 = input.shift
|
701
|
-
op = input.shift
|
702
|
-
|
703
|
-
if types.include? op.type
|
704
|
-
n1 = input.shift
|
705
|
-
|
706
|
-
result = block_given? ?
|
707
|
-
yield(n0,op,n1) :
|
708
|
-
node(:call, op, n0, op.sym, node(:array, n1, [n1]))
|
709
|
-
input.unshift result
|
710
|
-
else
|
711
|
-
output.push n0
|
712
|
-
output.push op
|
713
|
-
end
|
714
|
-
end
|
715
|
-
|
716
|
-
# Push the last item remaining
|
717
|
-
output.push input.shift
|
718
|
-
|
719
|
-
input.replace output
|
720
|
-
end
|
721
|
-
|
722
|
-
# Given a locator and an node(:array), refactor the splat-related nodes
|
723
|
-
# in a copy of the original node body and return a replacement for the node.
|
724
|
-
#
|
725
|
-
def args_assemble loc, orig_node
|
726
|
-
list = orig_node.body.dup
|
727
|
-
tmp = []
|
728
|
-
|
729
|
-
special_type_check = Proc.new { |x|
|
730
|
-
case x
|
731
|
-
when Myco::ToolSet::AST::SplatValue; :splat
|
732
|
-
when Myco::ToolSet::AST::ConcatArgs; :argscat
|
733
|
-
when Myco::ToolSet::AST::PushArgs; :argspush
|
734
|
-
when Myco::ToolSet::AST::BlockPass; :block_pass
|
735
|
-
else; nil
|
736
|
-
end
|
737
|
-
}
|
738
|
-
|
739
|
-
# Get the original value in the new_node
|
740
|
-
tmp << list.shift until list.empty? or special_type_check.call(list.first)
|
741
|
-
new_node = tmp.empty? ? list.shift : node(:array, loc, tmp)
|
742
|
-
|
743
|
-
# Continue to reduce until all elements have been used
|
744
|
-
until list.empty?
|
745
|
-
arg = list.shift
|
746
|
-
type = special_type_check.call(arg)
|
747
|
-
if type == :block_pass
|
748
|
-
new_node = arg.tap { |n| n.arguments = new_node }
|
749
|
-
elsif type != nil
|
750
|
-
new_node = node(:argscat, loc, new_node, arg)
|
751
|
-
else
|
752
|
-
new_node = node(:argspush, loc, new_node, arg)
|
753
|
-
end
|
754
|
-
end
|
755
|
-
|
756
|
-
new_node || orig_node
|
757
|
-
end
|
758
|
-
|
759
|
-
}
|