minjs 0.2.2 → 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.
- checksums.yaml +4 -4
- data/exe/minjs +12 -2
- data/lib/minjs.rb +0 -1
- data/lib/minjs/compressor.rb +24 -21
- data/lib/minjs/ctype.rb +1239 -836
- data/lib/minjs/ecma262/base.rb +1 -1
- data/lib/minjs/ecma262/exp.rb +31 -2
- data/lib/minjs/ecma262/lit.rb +103 -56
- data/lib/minjs/ecma262/punc.rb +6 -2
- data/lib/minjs/ecma262/st.rb +7 -3
- data/lib/minjs/exceptions.rb +3 -3
- data/lib/minjs/expression.rb +597 -496
- data/lib/minjs/func.rb +80 -66
- data/lib/minjs/lex.rb +629 -407
- data/lib/minjs/program.rb +16 -12
- data/lib/minjs/statement.rb +321 -309
- data/lib/minjs/version.rb +1 -1
- metadata +2 -3
- data/lib/minjs/literal.rb +0 -45
data/lib/minjs/func.rb
CHANGED
@@ -1,92 +1,106 @@
|
|
1
1
|
module Minjs
|
2
2
|
module Func
|
3
|
-
#
|
4
3
|
#13
|
5
4
|
#
|
5
|
+
# FunctionDeclaration :
|
6
|
+
# function Identifier ( FormalParameterListopt ) { FunctionBody }
|
7
|
+
#
|
8
|
+
# NOTE:
|
9
|
+
#
|
10
|
+
# The function declaration in statement(block) is not permitted by ECMA262.
|
11
|
+
# However, almost all implementation permit it.
|
12
|
+
#
|
6
13
|
def func_declaration(lex, context)
|
7
|
-
return nil if lex.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
14
|
+
return nil if lex.eql_lit?(ECMA262::ID_FUNCTION).nil?
|
15
|
+
|
16
|
+
new_context = ECMA262::Context.new
|
17
|
+
new_context.lex_env = context.lex_env.new_declarative_env()
|
18
|
+
new_context.var_env = context.var_env.new_declarative_env()
|
12
19
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
if id=identifier(lex, context) and
|
21
|
+
lex.eql_lit?(ECMA262::PUNC_LPARENTHESIS) and
|
22
|
+
args = formal_parameter_list(lex, new_context) and
|
23
|
+
lex.eql_lit?(ECMA262::PUNC_RPARENTHESIS) and
|
24
|
+
lex.eql_lit?(ECMA262::PUNC_LCURLYBRAC) and
|
25
|
+
b=func_body(lex, new_context) and lex.eql_lit?(ECMA262::PUNC_RCURLYBRAC)
|
26
|
+
f = ECMA262::StFunc.new(new_context, id, args, b, {:decl => true})
|
20
27
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
context.var_env.record.create_mutable_binding(id, nil)
|
29
|
+
context.var_env.record.set_mutable_binding(id, f, nil)
|
30
|
+
context.lex_env.record.create_mutable_binding(id, nil)
|
31
|
+
context.lex_env.record.set_mutable_binding(id, f, nil)
|
32
|
+
f
|
33
|
+
else
|
34
|
+
if b
|
35
|
+
raise ParseError.new("No `}' at end of function", lex)
|
26
36
|
else
|
27
|
-
|
28
|
-
raise ParseError.new("No `}' at end of function", lex)
|
29
|
-
else
|
30
|
-
raise ParseError.new("Bad function declaration", lex)
|
31
|
-
end
|
37
|
+
raise ParseError.new("Bad function declaration", lex)
|
32
38
|
end
|
33
|
-
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
42
|
+
#13
|
43
|
+
#
|
44
|
+
# FunctionExpression :
|
45
|
+
# function Identifieropt ( FormalParameterListopt ) { FunctionBody }
|
46
|
+
#
|
36
47
|
def func_exp(lex, context)
|
37
|
-
return nil if lex.
|
48
|
+
return nil if lex.eql_lit?(ECMA262::ID_FUNCTION).nil?
|
38
49
|
@logger.debug "*** func_exp"
|
39
50
|
|
40
|
-
lex
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
new_context.var_env = context.var_env.new_declarative_env()
|
51
|
+
id_opt = identifier(lex, context)
|
52
|
+
new_context = ECMA262::Context.new
|
53
|
+
new_context.lex_env = context.lex_env.new_declarative_env()
|
54
|
+
new_context.var_env = context.var_env.new_declarative_env()
|
45
55
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
}
|
56
|
+
if lex.eql_lit?(ECMA262::PUNC_LPARENTHESIS) and
|
57
|
+
args = formal_parameter_list(lex, new_context) and
|
58
|
+
lex.eql_lit?(ECMA262::PUNC_RPARENTHESIS) and
|
59
|
+
lex.eql_lit?(ECMA262::PUNC_LCURLYBRAC) and
|
60
|
+
b = func_body(lex, new_context) and lex.eql_lit?(ECMA262::PUNC_RCURLYBRAC)
|
61
|
+
f = ECMA262::StFunc.new(new_context, id_opt, args, b)
|
62
|
+
if id_opt
|
63
|
+
new_context.var_env.record.create_mutable_binding(id_opt, nil)
|
64
|
+
new_context.var_env.record.set_mutable_binding(id_opt, f, nil)
|
65
|
+
new_context.lex_env.record.create_mutable_binding(id_opt, nil)
|
66
|
+
new_context.lex_env.record.set_mutable_binding(id_opt, f, nil)
|
67
|
+
id_opt.context = new_context
|
68
|
+
end
|
69
|
+
f
|
70
|
+
else
|
71
|
+
if b
|
72
|
+
raise ParseError.new("No `}' at end of function", lex)
|
73
|
+
else
|
74
|
+
raise ParseError.new("Bad function expression", lex)
|
75
|
+
end
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
70
79
|
def formal_parameter_list(lex, context)
|
71
|
-
|
72
|
-
|
80
|
+
ret = []
|
81
|
+
unless lex.peek_lit(nil).eql? ECMA262::PUNC_RPARENTHESIS
|
73
82
|
while true
|
74
|
-
|
75
|
-
|
76
|
-
ret.push(a)
|
77
|
-
break if lex.match_lit(ECMA262::PUNC_COMMA).nil?
|
83
|
+
if arg = identifier(lex, context)
|
84
|
+
ret.push(arg)
|
78
85
|
else
|
86
|
+
raise ParseError.new("unexpceted token", lex)
|
87
|
+
end
|
88
|
+
if lex.peek_lit(nil).eql? ECMA262::PUNC_RPARENTHESIS
|
79
89
|
break
|
90
|
+
elsif lex.eql_lit? ECMA262::PUNC_COMMA
|
91
|
+
;
|
92
|
+
else
|
93
|
+
raise ParseError.new("unexpceted token", lex)
|
80
94
|
end
|
81
95
|
end
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
96
|
+
end
|
97
|
+
ret.each do |argName|
|
98
|
+
context.var_env.record.create_mutable_binding(argName, nil)
|
99
|
+
context.var_env.record.set_mutable_binding(argName, :undefined, nil, {:_parameter_list => true})
|
100
|
+
context.lex_env.record.create_mutable_binding(argName, nil)
|
101
|
+
context.lex_env.record.set_mutable_binding(argName, :undefined, nil, {:_parameter_list => true})
|
102
|
+
end
|
103
|
+
ret
|
90
104
|
end
|
91
105
|
|
92
106
|
def func_body(lex, context)
|
data/lib/minjs/lex.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require 'minjs/ctype'
|
2
3
|
|
3
4
|
module Minjs
|
@@ -5,58 +6,87 @@ module Minjs
|
|
5
6
|
include Ctype
|
6
7
|
|
7
8
|
attr_reader :pos
|
8
|
-
attr_reader :error_pos
|
9
9
|
attr_reader :codes
|
10
10
|
|
11
11
|
def initialize(str = "", options = {})
|
12
12
|
str = str.gsub(/\r\n/, "\n")
|
13
13
|
@codes = str.codepoints
|
14
|
+
if !str.match(/\n\z/)
|
15
|
+
@codes.push(10)
|
16
|
+
end
|
14
17
|
@pos = 0
|
15
18
|
@lit_cache = []
|
16
19
|
@lit_nextpos = []
|
17
20
|
@logger = options[:logger]
|
21
|
+
|
22
|
+
@eval_nest = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear_cache
|
26
|
+
@lit_cache = []
|
27
|
+
@lit_nextpos = []
|
18
28
|
end
|
19
29
|
|
20
|
-
|
21
|
-
|
22
|
-
|
30
|
+
#
|
31
|
+
# Fetch next literal
|
32
|
+
#
|
33
|
+
# hint:
|
34
|
+
# :regexp
|
35
|
+
# :div
|
36
|
+
# nil
|
37
|
+
#
|
38
|
+
# ECMA262 says:
|
39
|
+
#
|
40
|
+
# There are no syntactic grammar contexts where both a leading division
|
41
|
+
# or division-assignment, and a leading RegularExpressionLiteral are permitted.
|
42
|
+
# This is not affected by semicolon insertion (see 7.9); in examples such as the following:
|
43
|
+
# To determine `/' is regular expression or not
|
44
|
+
#
|
45
|
+
def next_input_element(hint)
|
46
|
+
if ret = @lit_cache[@pos]
|
23
47
|
@pos = @lit_nextpos[@pos]
|
24
|
-
@
|
48
|
+
@head_pos = @pos
|
25
49
|
return ret
|
26
50
|
end
|
27
51
|
pos0 = @pos
|
28
|
-
if ret = (white_space || line_terminator || comment || token)
|
29
|
-
if ret
|
30
|
-
@lit_cache[pos0] = ret
|
31
|
-
@lit_nextpos[pos0] = @pos
|
32
|
-
end
|
33
|
-
@error_pos = @pos
|
34
|
-
return ret
|
35
|
-
end
|
36
|
-
#
|
37
|
-
# ECMA262 say:
|
38
52
|
#
|
39
|
-
#
|
40
|
-
# or division-assignment, and a leading RegularExpressionLiteral are permitted.
|
41
|
-
# This is not affected by semicolon insertion (see 7.9); in examples such as the following:
|
42
|
-
# To determine `/' is regular expression or not
|
53
|
+
# skip white space here, because ECMA262(5.1.2) says:
|
43
54
|
#
|
55
|
+
# Simple white space and single-line comments are discarded and
|
56
|
+
# do not appear in the stream of input elements for the
|
57
|
+
# syntactic grammar.
|
44
58
|
#
|
45
|
-
|
59
|
+
while white_space or single_line_comment
|
60
|
+
end
|
61
|
+
|
62
|
+
ret = line_terminator || multi_line_comment || token
|
63
|
+
if ret
|
64
|
+
@lit_cache[pos0] = ret
|
65
|
+
@lit_nextpos[pos0] = @pos
|
66
|
+
@head_pos = @pos
|
67
|
+
return ret
|
68
|
+
end
|
69
|
+
|
70
|
+
if @codes[@pos].nil?
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
if hint.nil?
|
74
|
+
ECMA262::LIT_DIV_OR_REGEXP_LITERAL
|
75
|
+
elsif hint == :div
|
46
76
|
ret = div_punctuator
|
47
77
|
if ret
|
48
78
|
@lit_cache[pos0] = ret
|
49
79
|
@lit_nextpos[pos0] = @pos
|
50
80
|
end
|
51
|
-
@
|
81
|
+
@head_pos = @pos
|
52
82
|
return ret
|
53
|
-
elsif
|
83
|
+
elsif hint == :regexp
|
54
84
|
ret = regexp_literal
|
55
85
|
if ret
|
56
86
|
@lit_cache[pos0] = ret
|
57
87
|
@lit_nextpos[pos0] = @pos
|
58
88
|
end
|
59
|
-
@
|
89
|
+
@head_pos = @pos
|
60
90
|
return ret
|
61
91
|
else
|
62
92
|
ECMA262::LIT_DIV_OR_REGEXP_LITERAL
|
@@ -65,13 +95,10 @@ module Minjs
|
|
65
95
|
|
66
96
|
# 7.2
|
67
97
|
def white_space
|
68
|
-
|
69
|
-
|
70
|
-
while true
|
98
|
+
if white_space?(@codes[@pos])
|
99
|
+
begin
|
71
100
|
@pos += 1
|
72
|
-
|
73
|
-
break unless white_space?(code)
|
74
|
-
end
|
101
|
+
end until !white_space?(@codes[@pos])
|
75
102
|
return ECMA262::WhiteSpace.get
|
76
103
|
else
|
77
104
|
nil
|
@@ -80,13 +107,10 @@ module Minjs
|
|
80
107
|
|
81
108
|
#7.3
|
82
109
|
def line_terminator
|
83
|
-
|
84
|
-
|
85
|
-
while true
|
110
|
+
if line_terminator?(@codes[@pos])
|
111
|
+
begin
|
86
112
|
@pos += 1
|
87
|
-
|
88
|
-
break unless line_terminator?(code)
|
89
|
-
end
|
113
|
+
end until !line_terminator?(@codes[@pos])
|
90
114
|
return ECMA262::LineFeed.get
|
91
115
|
else
|
92
116
|
nil
|
@@ -99,38 +123,31 @@ module Minjs
|
|
99
123
|
end
|
100
124
|
|
101
125
|
def multi_line_comment
|
126
|
+
# /*
|
102
127
|
if @codes[@pos] == 0x2f and @codes[@pos + 1] == 0x2a
|
103
|
-
@pos
|
128
|
+
@pos += 2
|
104
129
|
pos0 = @pos
|
105
|
-
|
106
|
-
while (@codes[@pos] != 0x2a or @codes[@pos + 1] != 0x2f
|
107
|
-
if
|
108
|
-
|
109
|
-
end
|
110
|
-
if line_terminator?(@codes[@pos])
|
111
|
-
lf = true
|
112
|
-
end
|
113
|
-
@pos = @pos + 1
|
130
|
+
# */
|
131
|
+
while (code = @codes[@pos] != 0x2a) or @codes[@pos + 1] != 0x2f
|
132
|
+
raise ParseError.new("no `*/' at end of comment", self) if code.nil?
|
133
|
+
@pos += 1
|
114
134
|
end
|
115
|
-
@pos
|
116
|
-
return ECMA262::MultiLineComment.new(@codes[pos0...(@pos-2)].pack("U*")
|
135
|
+
@pos +=2
|
136
|
+
return ECMA262::MultiLineComment.new(@codes[pos0...(@pos-2)].pack("U*"))
|
117
137
|
else
|
118
138
|
nil
|
119
139
|
end
|
120
140
|
end
|
121
141
|
|
122
142
|
def single_line_comment
|
143
|
+
# //
|
123
144
|
if @codes[@pos] == 0x2f and @codes[@pos + 1] == 0x2f
|
124
|
-
@pos
|
145
|
+
@pos += 2
|
125
146
|
pos0 = @pos
|
126
|
-
while
|
147
|
+
while (code = @codes[@pos]) and !line_terminator?(code)
|
127
148
|
@pos += 1
|
128
149
|
end
|
129
|
-
|
130
|
-
return ECMA262::SingleLineComment.new(@codes[pos0...@pos].pack("U*") + "\n")
|
131
|
-
else
|
132
|
-
return ECMA262::SingleLineComment.new(@codes[pos0...@pos].pack("U*"))
|
133
|
-
end
|
150
|
+
return ECMA262::SingleLineComment.new(@codes[pos0...@pos].pack("U*"))
|
134
151
|
else
|
135
152
|
nil
|
136
153
|
end
|
@@ -140,38 +157,36 @@ module Minjs
|
|
140
157
|
# 7.5 tokens
|
141
158
|
#
|
142
159
|
def token
|
143
|
-
|
144
|
-
ret = (identifier_name || numeric_literal || punctuator || string_literal)
|
145
|
-
if ret
|
146
|
-
@lit_cache[pos0] = ret
|
147
|
-
@lit_nextpos[pos0] = @pos
|
148
|
-
end
|
149
|
-
ret
|
160
|
+
identifier_name || numeric_literal || punctuator || string_literal
|
150
161
|
end
|
151
162
|
|
163
|
+
#
|
152
164
|
def unicode_escape?
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
165
|
+
# @codes[@pos] == 0x5c
|
166
|
+
if @codes[@pos+1] == 0x75 #u
|
167
|
+
if hex_digit?(@codes[@pos+2]) and
|
168
|
+
hex_digit?(@codes[@pos+3]) and
|
169
|
+
hex_digit?(@codes[@pos+4]) and
|
170
|
+
hex_digit?(@codes[@pos+5])
|
171
|
+
@codes[(@pos+2)..(@pos+5)].pack("U*").to_i(16)
|
172
|
+
else
|
173
|
+
raise ParseError.new("bad unicode escpae sequence", self)
|
174
|
+
end
|
160
175
|
else
|
161
|
-
|
176
|
+
nil
|
162
177
|
end
|
163
178
|
end
|
164
179
|
|
165
180
|
def identifier_name
|
166
|
-
|
167
|
-
return nil if @codes[@pos].nil?
|
181
|
+
return nil if (code = @codes[@pos]).nil?
|
168
182
|
|
183
|
+
pos0 = @pos
|
169
184
|
chars = []
|
170
|
-
if
|
171
|
-
chars.push(
|
185
|
+
if code == 0x5c and ucode = unicode_escape? and identifier_start?(ucode)
|
186
|
+
chars.push(ucode)
|
172
187
|
@pos += 6
|
173
|
-
elsif identifier_start?(
|
174
|
-
chars.push(
|
188
|
+
elsif identifier_start?(code)
|
189
|
+
chars.push(code)
|
175
190
|
@pos += 1
|
176
191
|
else
|
177
192
|
return nil
|
@@ -179,15 +194,15 @@ module Minjs
|
|
179
194
|
|
180
195
|
while true
|
181
196
|
code = @codes[@pos]
|
182
|
-
if
|
183
|
-
chars.push(
|
197
|
+
if code == 0x5c and ucode = unicode_escape? and identifier_part?(ucode)
|
198
|
+
chars.push(ucode)
|
184
199
|
@pos += 6
|
185
|
-
elsif identifier_part?(
|
186
|
-
chars.push(
|
200
|
+
elsif identifier_part?(code)
|
201
|
+
chars.push(code)
|
187
202
|
@pos += 1
|
188
203
|
else
|
189
204
|
name = chars.pack("U*").to_sym
|
190
|
-
return ECMA262::IdentifierName.
|
205
|
+
return ECMA262::IdentifierName.get(nil, name)
|
191
206
|
end
|
192
207
|
end
|
193
208
|
end
|
@@ -197,148 +212,167 @@ module Minjs
|
|
197
212
|
code1 = @codes[@pos+1]
|
198
213
|
code2 = @codes[@pos+2]
|
199
214
|
code3 = @codes[@pos+3]
|
200
|
-
if
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
@pos +=
|
266
|
-
return ECMA262::
|
267
|
-
elsif
|
268
|
-
@pos +=
|
269
|
-
return ECMA262::
|
270
|
-
elsif
|
271
|
-
@pos +=
|
272
|
-
return ECMA262::
|
273
|
-
elsif
|
274
|
-
@pos += 1
|
275
|
-
return ECMA262::
|
276
|
-
elsif
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
@pos += 1
|
290
|
-
return ECMA262::
|
291
|
-
elsif
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
215
|
+
if code0 == 0x21 # !
|
216
|
+
if code1 == 0x3d and code2 == 0x3d # !==
|
217
|
+
@pos += 3
|
218
|
+
return ECMA262::PUNC_SNEQ
|
219
|
+
end
|
220
|
+
if code1 == 0x3d # !=
|
221
|
+
@pos += 2
|
222
|
+
return ECMA262::PUNC_NEQ
|
223
|
+
end
|
224
|
+
@pos += 1 # !
|
225
|
+
return ECMA262::PUNC_LNOT
|
226
|
+
elsif code0 == 0x25 # %
|
227
|
+
if code1 == 0x3d # %=
|
228
|
+
@pos += 2
|
229
|
+
return ECMA262::PUNC_MODLET
|
230
|
+
end
|
231
|
+
@pos += 1 # %
|
232
|
+
return ECMA262::PUNC_MOD
|
233
|
+
elsif code0 == 0x26 # &
|
234
|
+
if code1 == 0x3d # &=
|
235
|
+
@pos += 2
|
236
|
+
return ECMA262::PUNC_ANDLET
|
237
|
+
end
|
238
|
+
if code1 == 0x26 # &&
|
239
|
+
@pos += 2
|
240
|
+
return ECMA262::PUNC_LAND
|
241
|
+
end
|
242
|
+
@pos += 1 # &
|
243
|
+
return ECMA262::PUNC_AND
|
244
|
+
elsif code0 == 0x28 # (
|
245
|
+
@pos += 1 # (
|
246
|
+
return ECMA262::PUNC_LPARENTHESIS
|
247
|
+
elsif code0 == 0x29 # )
|
248
|
+
@pos += 1 # )
|
249
|
+
return ECMA262::PUNC_RPARENTHESIS
|
250
|
+
elsif code0 == 0x2a # *
|
251
|
+
if code1 == 0x3d # *=
|
252
|
+
@pos += 2
|
253
|
+
return ECMA262::PUNC_MULLET
|
254
|
+
end
|
255
|
+
@pos += 1 # *
|
256
|
+
return ECMA262::PUNC_MUL
|
257
|
+
elsif code0 == 0x2b # +
|
258
|
+
if code1 == 0x3d # +=
|
259
|
+
@pos += 2
|
260
|
+
return ECMA262::PUNC_ADDLET
|
261
|
+
end
|
262
|
+
if code1 == 0x2b # ++
|
263
|
+
@pos += 2
|
264
|
+
return ECMA262::PUNC_INC
|
265
|
+
end
|
266
|
+
@pos += 1 # +
|
267
|
+
return ECMA262::PUNC_ADD
|
268
|
+
elsif code0 == 0x2c # ,
|
269
|
+
@pos += 1 # ,
|
270
|
+
return ECMA262::PUNC_COMMA
|
271
|
+
elsif code0 == 0x2d # -
|
272
|
+
if code1 == 0x3d # -=
|
273
|
+
@pos += 2
|
274
|
+
return ECMA262::PUNC_SUBLET
|
275
|
+
end
|
276
|
+
if code1 == 0x2d # --
|
277
|
+
@pos += 2
|
278
|
+
return ECMA262::PUNC_DEC
|
279
|
+
end
|
280
|
+
@pos += 1 # -
|
281
|
+
return ECMA262::PUNC_SUB
|
282
|
+
elsif code0 == 0x2e # .
|
283
|
+
@pos += 1 # .
|
284
|
+
return ECMA262::PUNC_PERIOD
|
285
|
+
elsif code0 == 0x3a # :
|
286
|
+
@pos += 1 # :
|
287
|
+
return ECMA262::PUNC_COLON
|
288
|
+
elsif code0 == 0x3b # ;
|
289
|
+
@pos += 1 # ;
|
290
|
+
return ECMA262::PUNC_SEMICOLON
|
291
|
+
elsif code0 == 0x3c # <
|
292
|
+
if code1 == 0x3d # <=
|
293
|
+
@pos += 2
|
294
|
+
return ECMA262::PUNC_LTEQ
|
295
|
+
end
|
296
|
+
if code1 == 0x3c and code2 == 0x3d # <<=
|
297
|
+
@pos += 3
|
298
|
+
return ECMA262::PUNC_LSHIFTLET
|
299
|
+
end
|
300
|
+
if code1 == 0x3c # <<
|
301
|
+
@pos += 2
|
302
|
+
return ECMA262::PUNC_LSHIFT
|
303
|
+
end
|
304
|
+
@pos += 1 # <
|
305
|
+
return ECMA262::PUNC_LT
|
306
|
+
elsif code0 == 0x3d # =
|
307
|
+
if code1 == 0x3d and code2 == 0x3d # ===
|
308
|
+
@pos += 3
|
309
|
+
return ECMA262::PUNC_SEQ
|
310
|
+
end
|
311
|
+
if code1 == 0x3d # ==
|
312
|
+
@pos += 2
|
313
|
+
return ECMA262::PUNC_EQ
|
314
|
+
end
|
315
|
+
@pos += 1 # =
|
316
|
+
return ECMA262::PUNC_LET
|
317
|
+
elsif code0 == 0x3e # >
|
318
|
+
if code1 == 0x3e and code2 == 0x3e and code3 == 0x3d # >>>=
|
319
|
+
@pos += 4
|
320
|
+
return ECMA262::PUNC_URSHIFTLET
|
321
|
+
end
|
322
|
+
if code1 == 0x3e and code2 == 0x3e # >>>
|
323
|
+
@pos += 3
|
324
|
+
return ECMA262::PUNC_URSHIFT
|
325
|
+
end
|
326
|
+
if code1 == 0x3e and code2 == 0x3d # >>=
|
327
|
+
@pos += 3
|
328
|
+
return ECMA262::PUNC_RSHIFTLET
|
329
|
+
end
|
330
|
+
if code1 == 0x3e # >>
|
331
|
+
@pos += 2
|
332
|
+
return ECMA262::PUNC_RSHIFT
|
333
|
+
end
|
334
|
+
if code1 == 0x3d # >=
|
335
|
+
@pos += 2
|
336
|
+
return ECMA262::PUNC_GTEQ
|
337
|
+
end
|
338
|
+
@pos += 1 # >
|
339
|
+
return ECMA262::PUNC_GT
|
340
|
+
elsif code0 == 0x3f # ?
|
341
|
+
@pos += 1 # ?
|
342
|
+
return ECMA262::PUNC_CONDIF
|
343
|
+
elsif code0 == 0x5b # [
|
344
|
+
@pos += 1 # [
|
345
|
+
return ECMA262::PUNC_LSQBRAC
|
346
|
+
elsif code0 == 0x5d # ]
|
347
|
+
@pos += 1 # ]
|
348
|
+
return ECMA262::PUNC_RSQBRAC
|
349
|
+
elsif code0 == 0x5e # ^
|
350
|
+
if code1 == 0x3d # ^=
|
351
|
+
@pos += 2
|
352
|
+
return ECMA262::PUNC_XORLET
|
353
|
+
end
|
354
|
+
@pos += 1 # ^
|
355
|
+
return ECMA262::PUNC_XOR
|
356
|
+
elsif code0 == 0x7b # {
|
357
|
+
@pos += 1 # {
|
358
|
+
return ECMA262::PUNC_LCURLYBRAC
|
359
|
+
elsif code0 == 0x7c # |
|
360
|
+
if code1 == 0x7c # ||
|
361
|
+
@pos += 2
|
362
|
+
return ECMA262::PUNC_LOR
|
363
|
+
end
|
364
|
+
if code1 == 0x3d # |=
|
365
|
+
@pos += 2
|
366
|
+
return ECMA262::PUNC_ORLET
|
367
|
+
end
|
368
|
+
@pos += 1 # |
|
369
|
+
return ECMA262::PUNC_OR
|
370
|
+
elsif code0 == 0x7d # }
|
371
|
+
@pos += 1 # }
|
372
|
+
return ECMA262::PUNC_RCURLYBRAC
|
373
|
+
elsif code0 == 0x7e # ~
|
374
|
+
@pos += 1 # ~
|
375
|
+
return ECMA262::PUNC_NOT
|
342
376
|
end
|
343
377
|
nil
|
344
378
|
end
|
@@ -434,68 +468,124 @@ module Minjs
|
|
434
468
|
end
|
435
469
|
|
436
470
|
#7.8.3
|
471
|
+
#B.1.1
|
437
472
|
def numeric_literal
|
438
|
-
|
439
|
-
return nil if code.nil?
|
440
|
-
|
441
|
-
hex_integer_literal || decimal_literal
|
473
|
+
hex_integer_literal || octal_integer_literal || decimal_literal
|
442
474
|
end
|
443
475
|
|
476
|
+
#7.8.3
|
477
|
+
#
|
478
|
+
# HexIntegerLiteral ::
|
479
|
+
# 0x HexDigit
|
480
|
+
# 0X HexDigit
|
481
|
+
# HexIntegerLiteral HexDigit
|
482
|
+
#
|
444
483
|
def hex_integer_literal
|
445
|
-
pos0 = @pos
|
446
|
-
# 0x.... or 0X....
|
447
484
|
code = @codes[@pos]
|
448
|
-
if code
|
485
|
+
if code.nil?
|
486
|
+
return nil
|
487
|
+
#0x / 0X
|
488
|
+
elsif code == 0x30 and (@codes[@pos+1] == 0x78 || @codes[@pos+1] == 0x58)
|
449
489
|
@pos += 2
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
490
|
+
pos0 = @pos
|
491
|
+
while code = @codes[@pos] and hex_digit?(code)
|
492
|
+
@pos += 1;
|
493
|
+
end
|
494
|
+
if identifier_start?(code)
|
495
|
+
raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
|
496
|
+
else
|
497
|
+
return ECMA262::ECMA262Numeric.new(@codes[pos0...@pos].pack("U*").to_i(16))
|
498
|
+
end
|
499
|
+
else
|
500
|
+
nil
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
#B.1.1
|
505
|
+
# OctalIntegerLiteral ::
|
506
|
+
# 0 OctalDigit
|
507
|
+
# OctalIntegerLiteral OctalDigit
|
508
|
+
#
|
509
|
+
def octal_integer_literal
|
510
|
+
code = @codes[@pos]
|
511
|
+
if code.nil?
|
512
|
+
return nil
|
513
|
+
elsif code == 0x30 and (code1 = @codes[@pos + 1]) >= 0x30 and code1 <= 0x37
|
514
|
+
@pos += 1
|
515
|
+
pos0 = @pos
|
516
|
+
while code = @codes[@pos] and code >= 0x30 and code <= 0x37
|
459
517
|
@pos += 1
|
460
518
|
end
|
519
|
+
if identifier_start?(code)
|
520
|
+
raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
|
521
|
+
else
|
522
|
+
return ECMA262::ECMA262Numeric.new(@codes[pos0...@pos].pack("U*").to_i(8))
|
523
|
+
end
|
461
524
|
else
|
462
525
|
nil
|
463
526
|
end
|
464
527
|
end
|
465
528
|
|
529
|
+
# 7.8.3
|
530
|
+
#
|
531
|
+
# DecimalLiteral ::
|
532
|
+
# DecimalIntegerLiteral . DecimalDigitsopt ExponentPartopt
|
533
|
+
# . DecimalDigits ExponentPartopt
|
534
|
+
# DecimalIntegerLiteral ExponentPartopt
|
535
|
+
#
|
466
536
|
def decimal_literal
|
467
537
|
pos0 = @pos
|
468
538
|
code = @codes[@pos]
|
469
|
-
|
539
|
+
|
540
|
+
if code.nil?
|
541
|
+
return nil
|
542
|
+
elsif code == 0x2e #.
|
470
543
|
@pos += 1
|
471
544
|
f = decimal_digits
|
472
|
-
if f.nil?
|
473
|
-
@pos = pos0
|
474
|
-
return
|
545
|
+
if f.nil? #=> this period is punctuator
|
546
|
+
@pos = pos0 + 1
|
547
|
+
return ECMA262::PUNC_PERIOD
|
475
548
|
end
|
476
|
-
if @codes[@pos] == 0x65 ||
|
549
|
+
if (code = @codes[@pos]) == 0x65 || code == 0x45
|
477
550
|
@pos += 1
|
478
|
-
e =
|
551
|
+
e = exponent_part
|
479
552
|
end
|
480
553
|
if identifier_start?(@codes[@pos])
|
481
554
|
raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
|
482
555
|
end
|
483
556
|
|
484
557
|
return ECMA262::ECMA262Numeric.new('0', f, e)
|
485
|
-
|
558
|
+
elsif code == 0x30 # zero
|
559
|
+
i = "0"
|
560
|
+
@pos += 1
|
561
|
+
if @codes[@pos] == 0x2e #.
|
562
|
+
@pos += 1
|
563
|
+
f = decimal_digits
|
564
|
+
if (code = @codes[@pos]) == 0x65 || code == 0x45 #e or E
|
565
|
+
@pos += 1
|
566
|
+
e = exponent_part
|
567
|
+
end
|
568
|
+
elsif (code = @codes[@pos]) == 0x65 || code == 0x45 #e or E
|
569
|
+
@pos += 1
|
570
|
+
e = exponent_part
|
571
|
+
end
|
572
|
+
if identifier_start?(@codes[@pos])
|
573
|
+
raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
|
574
|
+
end
|
486
575
|
|
487
|
-
|
576
|
+
return ECMA262::ECMA262Numeric.new(i, f, e)
|
577
|
+
elsif code >= 0x31 and code <= 0x39
|
488
578
|
i = decimal_digits
|
489
579
|
if @codes[@pos] == 0x2e #.
|
490
580
|
@pos += 1
|
491
581
|
f = decimal_digits
|
492
|
-
if @codes[@pos] == 0x65 ||
|
582
|
+
if (code = @codes[@pos]) == 0x65 || code == 0x45 #e or E
|
493
583
|
@pos += 1
|
494
|
-
e =
|
584
|
+
e = exponent_part
|
495
585
|
end
|
496
|
-
elsif @codes[@pos] == 0x65 ||
|
586
|
+
elsif (code = @codes[@pos]) == 0x65 || code == 0x45 #e or E
|
497
587
|
@pos += 1
|
498
|
-
e =
|
588
|
+
e = exponent_part
|
499
589
|
end
|
500
590
|
if identifier_start?(@codes[@pos])
|
501
591
|
raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
|
@@ -507,251 +597,334 @@ module Minjs
|
|
507
597
|
nil
|
508
598
|
end
|
509
599
|
|
510
|
-
|
511
|
-
|
600
|
+
# 7.8.3
|
601
|
+
#
|
602
|
+
# ExponentPart ::
|
603
|
+
# ExponentIndicator SignedInteger
|
604
|
+
#
|
605
|
+
def exponent_part
|
606
|
+
if (code = @codes[@pos]) == 0x2b
|
512
607
|
@pos += 1
|
513
|
-
elsif
|
608
|
+
elsif code == 0x2d
|
514
609
|
@pos += 1
|
515
610
|
neg = true
|
516
611
|
end
|
612
|
+
d = decimal_digits
|
613
|
+
raise ParseError.new("unexpecting token", self) if d.nil?
|
517
614
|
if neg
|
518
|
-
e = "-#{
|
615
|
+
e = "-#{d}"
|
519
616
|
else
|
520
|
-
e =
|
617
|
+
e = d
|
521
618
|
end
|
522
619
|
e
|
523
620
|
end
|
524
621
|
|
622
|
+
#7.8.3
|
623
|
+
#
|
624
|
+
# DecimalDigit :: one of
|
625
|
+
# 0 1 2 3 4 5 6 7 8 9
|
626
|
+
#
|
525
627
|
def decimal_digits
|
526
628
|
pos0 = @pos
|
527
|
-
code = @codes[@pos]
|
528
|
-
return nil if code.nil?
|
529
|
-
if code >= 0x30 and code <= 0x39
|
629
|
+
if (code = @codes[@pos]) >= 0x30 and code <= 0x39
|
530
630
|
@pos += 1
|
531
|
-
while
|
532
|
-
|
533
|
-
if code >= 0x30 and code <= 0x39
|
534
|
-
@pos += 1
|
535
|
-
else
|
536
|
-
return @codes[pos0...@pos].pack("U*")
|
537
|
-
end
|
631
|
+
while code = @codes[@pos] and code >= 0x30 and code <= 0x39
|
632
|
+
@pos += 1
|
538
633
|
end
|
634
|
+
return @codes[pos0...@pos].pack("U*")
|
539
635
|
else
|
540
636
|
nil
|
541
637
|
end
|
542
638
|
end
|
543
639
|
|
544
640
|
#7.8.4
|
641
|
+
#
|
642
|
+
# StringLiteral ::
|
643
|
+
# " DoubleStringCharactersopt "
|
644
|
+
# ' SingleStringCharactersopt '
|
645
|
+
#
|
646
|
+
# DoubleStringCharacters ::
|
647
|
+
# DoubleStringCharacter DoubleStringCharactersopt
|
648
|
+
#
|
649
|
+
# SingleStringCharacters ::
|
650
|
+
# SingleStringCharacter SingleStringCharactersopt
|
651
|
+
#
|
652
|
+
# DoubleStringCharacter ::
|
653
|
+
# SourceCharacter but not one of " or \ or LineTerminator
|
654
|
+
# \ EscapeSequence
|
655
|
+
# LineContinuation
|
656
|
+
#
|
657
|
+
# SingleStringCharacter ::
|
658
|
+
# SourceCharacter but not one of ' or \ or LineTerminator
|
659
|
+
# \ EscapeSequence
|
660
|
+
# LineContinuation
|
661
|
+
#
|
545
662
|
def string_literal
|
546
|
-
code = @codes[@pos]
|
547
|
-
return nil if code.nil?
|
548
|
-
pos0 = @pos
|
549
|
-
if code == 0x27 #'
|
663
|
+
if (code = @codes[@pos]) == 0x27 #'
|
550
664
|
term = 0x27
|
551
665
|
elsif code == 0x22 #"
|
552
666
|
term = 0x22
|
553
667
|
else
|
554
668
|
return nil
|
555
669
|
end
|
670
|
+
@pos += 1
|
671
|
+
pos0 = @pos
|
556
672
|
|
557
|
-
str =
|
558
|
-
while @codes[@pos]
|
559
|
-
@pos += 1
|
560
|
-
code = @codes[@pos]
|
673
|
+
str = []
|
674
|
+
while (code = @codes[@pos])
|
561
675
|
if code.nil?
|
562
676
|
raise ParseError.new("no `#{term}' at end of string", self)
|
563
677
|
elsif line_terminator?(code)
|
564
678
|
raise ParseError.new("string has line terminator in body", self)
|
565
679
|
elsif code == 0x5c #\
|
566
680
|
@pos += 1
|
567
|
-
str
|
681
|
+
str.push(escape_sequence)
|
568
682
|
elsif code == term
|
569
|
-
|
570
|
-
|
683
|
+
@pos += 1
|
684
|
+
return ECMA262::ECMA262String.new(str.compact.pack("U*"))
|
571
685
|
else
|
572
|
-
|
686
|
+
@pos += 1
|
687
|
+
str.push(code)
|
573
688
|
end
|
574
689
|
end
|
575
690
|
nil
|
576
691
|
end
|
577
692
|
|
578
|
-
#
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
693
|
+
# 7.8.4
|
694
|
+
# B.1.2
|
695
|
+
#
|
696
|
+
# EscapeSequence ::
|
697
|
+
# CharacterEscapeSequence
|
698
|
+
# 0 [lookahead ∉ DecimalDigit]
|
699
|
+
# HexEscapeSequence
|
700
|
+
# UnicodeEscapeSequence
|
701
|
+
# OctalEscapeSequence
|
702
|
+
|
703
|
+
def escape_sequence
|
704
|
+
case (code = @codes[@pos])
|
705
|
+
# when 0x30
|
706
|
+
# @pos += 1
|
707
|
+
# 0
|
708
|
+
when 0x27 #'
|
709
|
+
@pos += 1
|
710
|
+
0x27
|
711
|
+
when 0x22 #"
|
712
|
+
@pos += 1
|
713
|
+
0x22
|
714
|
+
when 0x5c #\
|
715
|
+
@pos += 1
|
716
|
+
0x5c
|
593
717
|
when 0x62 #b
|
594
|
-
|
718
|
+
@pos += 1
|
719
|
+
0x08
|
595
720
|
when 0x74 #t
|
596
|
-
|
721
|
+
@pos += 1
|
722
|
+
0x09
|
597
723
|
when 0x6e #n
|
598
|
-
|
724
|
+
@pos += 1
|
725
|
+
0x0a
|
599
726
|
when 0x76 #v
|
600
|
-
|
727
|
+
@pos += 1
|
728
|
+
0x0b
|
601
729
|
when 0x66 #f
|
602
|
-
|
730
|
+
@pos += 1
|
731
|
+
0x0c
|
603
732
|
when 0x72 #r
|
604
|
-
|
733
|
+
@pos += 1
|
734
|
+
0x0d
|
605
735
|
when 0x78 #x
|
606
|
-
|
607
|
-
@pos
|
736
|
+
#check
|
737
|
+
t = @codes[(@pos+1)..(@pos+2)].pack("U*").to_i(16)
|
738
|
+
@pos += 3
|
608
739
|
t
|
609
740
|
when 0x75 #u
|
610
|
-
|
611
|
-
@pos
|
741
|
+
#check
|
742
|
+
t = @codes[(@pos+1)..(@pos+4)].pack("U*").to_i(16)
|
743
|
+
@pos += 5
|
612
744
|
t
|
613
745
|
else
|
614
746
|
# line continuation
|
615
|
-
if line_terminator?(
|
616
|
-
|
617
|
-
|
618
|
-
# Annex B
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
747
|
+
if line_terminator?(code)
|
748
|
+
@pos += 1
|
749
|
+
nil
|
750
|
+
# Annex B.1.2
|
751
|
+
#
|
752
|
+
# OctalEscapeSequence ::
|
753
|
+
# OctalDigit [lookahead ∉ DecimalDigit]
|
754
|
+
# ZeroToThree OctalDigit [lookahead ∉ DecimalDigit]
|
755
|
+
# FourToSeven OctalDigit
|
756
|
+
# ZeroToThree OctalDigit OctalDigit
|
757
|
+
#
|
758
|
+
# Note:
|
759
|
+
#
|
760
|
+
# A string such as the following is invalid
|
761
|
+
# as a octal escape sequence.
|
762
|
+
#
|
763
|
+
# \19 or \319
|
764
|
+
#
|
765
|
+
# However, it is not to an error in most implementations.
|
766
|
+
# Therefore, minjs also intepret it such way.
|
767
|
+
#
|
768
|
+
elsif octal_digit?(code)
|
769
|
+
code1 = @codes[@pos+1]
|
770
|
+
code2 = @codes[@pos+2]
|
771
|
+
if code >= 0x30 and code <= 0x33
|
772
|
+
if octal_digit?(code1)
|
773
|
+
if octal_digit?(code2)
|
774
|
+
@pos += 3
|
775
|
+
(code - 0x30) * 64 + (code1 - 0x30) * 8 + (code2 - 0x30)
|
776
|
+
else
|
777
|
+
@pos += 2
|
778
|
+
(code - 0x30) * 8 + (code1 - 0x30)
|
779
|
+
end
|
780
|
+
else
|
781
|
+
@pos += 1
|
782
|
+
code - 0x30
|
783
|
+
end
|
784
|
+
else #if code >= 0x34 and code <= 0x37
|
785
|
+
if octal_digit?(code1)
|
786
|
+
@pos += 2
|
787
|
+
(code - 0x30) * 8 + (code1 - 0x30)
|
788
|
+
else
|
789
|
+
@pos += 1
|
790
|
+
code - 0x30
|
791
|
+
end
|
626
792
|
end
|
627
|
-
[oct].pack("U*")
|
628
793
|
else
|
629
|
-
|
794
|
+
@pos += 1
|
795
|
+
code
|
630
796
|
end
|
631
797
|
end
|
632
798
|
end
|
633
799
|
|
634
|
-
def eof?
|
635
|
-
|
636
|
-
pos = @pos
|
637
|
-
end
|
638
|
-
@codes[pos].nil?
|
800
|
+
def eof?
|
801
|
+
peek_lit(nil).nil?
|
639
802
|
end
|
640
803
|
|
641
804
|
#
|
642
|
-
# check next literal is 'l' or not
|
805
|
+
# check next literal is strictly equal to 'l' or not.
|
806
|
+
# white spaces and line terminators are skipped and ignored.
|
807
|
+
#
|
643
808
|
# if next literal is not 'l', position is not forwarded
|
644
809
|
# if next literal is 'l', position is forwarded
|
645
810
|
#
|
646
|
-
def
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
811
|
+
def eql_lit?(l, hint = nil)
|
812
|
+
lit = peek_lit(hint)
|
813
|
+
if lit.eql? l
|
814
|
+
fwd_after_peek
|
815
|
+
lit
|
816
|
+
else
|
817
|
+
nil
|
818
|
+
end
|
651
819
|
end
|
652
820
|
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
821
|
+
#
|
822
|
+
# check next literal is strictly equal to 'l' or not.
|
823
|
+
# white spaces are skipped and ignored.
|
824
|
+
# line terminators are not ignored.
|
825
|
+
#
|
826
|
+
# if next literal is not 'l', position is not forwarded
|
827
|
+
# if next literal is 'l', position is forwarded
|
828
|
+
#
|
829
|
+
def eql_lit_nolt?(l, hint = nil)
|
830
|
+
lit = peek_lit_nolt(hint)
|
831
|
+
if lit.eql? l
|
832
|
+
fwd_after_peek
|
833
|
+
lit
|
834
|
+
else
|
835
|
+
nil
|
663
836
|
end
|
664
|
-
@pos = pos0
|
665
|
-
lit
|
666
837
|
end
|
667
838
|
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
839
|
+
#
|
840
|
+
# check next literal is equal to 'l' or not.
|
841
|
+
# white spaces and line terminators are skipped and ignored.
|
842
|
+
#
|
843
|
+
# if next literal is not 'l', position is not forwarded
|
844
|
+
# if next literal is 'l', position is forwarded
|
845
|
+
#
|
846
|
+
def match_lit?(l, hint = nil)
|
847
|
+
lit = peek_lit(hint)
|
848
|
+
if lit == l
|
849
|
+
fwd_after_peek
|
850
|
+
lit
|
679
851
|
else
|
680
|
-
|
681
|
-
if lit and (lit.ws? or lit.lt?)
|
682
|
-
;
|
683
|
-
else
|
684
|
-
break
|
685
|
-
end
|
686
|
-
end
|
852
|
+
nil
|
687
853
|
end
|
688
|
-
lit
|
689
854
|
end
|
690
855
|
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
856
|
+
#
|
857
|
+
# check next literal is equal to 'l' or not.
|
858
|
+
# white spaces are skipped and ignored.
|
859
|
+
# line terminators are not ignored.
|
860
|
+
#
|
861
|
+
# if next literal is not 'l', position is not forwarded
|
862
|
+
# if next literal is 'l', position is forwarded
|
863
|
+
#
|
864
|
+
def match_lit_nolt?(l, hint = nil)
|
865
|
+
lit = peek_lit_nolt(hint)
|
866
|
+
if lit == l
|
867
|
+
fwd_after_peek
|
868
|
+
lit
|
695
869
|
else
|
696
870
|
nil
|
697
871
|
end
|
698
872
|
end
|
699
873
|
|
700
|
-
|
701
|
-
|
702
|
-
|
874
|
+
#
|
875
|
+
# fetch next literal.
|
876
|
+
# position is not forwarded.
|
877
|
+
# white spaces and line terminators are skipped and ignored.
|
878
|
+
#
|
879
|
+
def peek_lit(hint)
|
880
|
+
pos0 = @pos
|
881
|
+
while lit = next_input_element(hint) and (lit.ws? or lit.lt?)
|
703
882
|
end
|
883
|
+
@pos = pos0
|
884
|
+
lit
|
704
885
|
end
|
705
886
|
|
706
|
-
|
707
|
-
|
708
|
-
|
887
|
+
#
|
888
|
+
# fetch next literal.
|
889
|
+
# position is not forwarded.
|
890
|
+
# white spaces are skipped and ignored.
|
891
|
+
# line terminators are not ignored.
|
892
|
+
#
|
893
|
+
def peek_lit_nolt(hint)
|
894
|
+
pos0 = @pos
|
895
|
+
while lit = next_input_element(hint) and lit.ws?
|
709
896
|
end
|
710
|
-
@
|
897
|
+
@pos = pos0
|
898
|
+
lit
|
711
899
|
end
|
712
900
|
|
713
|
-
def
|
714
|
-
|
715
|
-
pos = @error_pos
|
716
|
-
if pos.nil?
|
717
|
-
pos = @pos
|
718
|
-
end
|
719
|
-
end
|
720
|
-
if pos > 20
|
721
|
-
pos -= 20
|
722
|
-
pos0 = 20
|
723
|
-
elsif pos >= 0
|
724
|
-
pos0 = pos
|
725
|
-
pos = 0
|
726
|
-
end
|
727
|
-
if col and col >= 1
|
728
|
-
pos0 = col - 1;
|
729
|
-
end
|
730
|
-
t = ''
|
731
|
-
t << @codes[pos..(pos+80)].pack("U*")
|
732
|
-
t << "\n"
|
733
|
-
t << (' ' * pos0) + "^"
|
734
|
-
t
|
901
|
+
def fwd_after_peek
|
902
|
+
@pos = @head_pos
|
735
903
|
end
|
736
904
|
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
905
|
+
#
|
906
|
+
# fetch next literal.
|
907
|
+
# position is forwarded.
|
908
|
+
# white spaces and line terminators are skipped and ignored.
|
909
|
+
#
|
910
|
+
def fwd_lit(hint)
|
911
|
+
while lit = next_input_element(hint) and (lit.ws? or lit.lt?)
|
743
912
|
end
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
913
|
+
lit
|
914
|
+
end
|
915
|
+
|
916
|
+
#
|
917
|
+
# fetch next literal.
|
918
|
+
# position is forwarded.
|
919
|
+
# white spaces are skipped and ignored.
|
920
|
+
# line terminators are not ignored.
|
921
|
+
#
|
922
|
+
def fwd_lit_nolt(hint)
|
923
|
+
while lit = next_input_element(hint) and lit.ws?
|
750
924
|
end
|
751
|
-
|
752
|
-
STDERR.puts @codes[pos..(pos+80)].collect{|u| u == 10 ? 0x20 : u}.pack("U*")
|
753
|
-
STDERR.puts (' ' * pos0) + "^"
|
925
|
+
lit
|
754
926
|
end
|
927
|
+
|
755
928
|
#
|
756
929
|
# break <val> => position is rewind, then break with <val>
|
757
930
|
# return <val> => position is rewind, then return <val>
|
@@ -760,17 +933,26 @@ module Minjs
|
|
760
933
|
def eval_lit(&block)
|
761
934
|
begin
|
762
935
|
saved_pos = @pos
|
936
|
+
@eval_nest += 1
|
763
937
|
ret = yield
|
764
938
|
ensure
|
939
|
+
@eval_nest -= 1
|
765
940
|
if ret.nil?
|
766
|
-
#@error_pos = @pos
|
767
941
|
@pos = saved_pos
|
768
942
|
nil
|
943
|
+
else
|
944
|
+
if @eval_nest == 0
|
945
|
+
#STDERR.puts "clear_cache [#{saved_pos}..#{@pos}]"
|
946
|
+
clear_cache
|
947
|
+
end
|
769
948
|
end
|
770
949
|
end
|
771
950
|
end
|
772
951
|
|
773
|
-
|
952
|
+
#
|
953
|
+
# position to [row, col]
|
954
|
+
#
|
955
|
+
def row_col(pos)
|
774
956
|
_pos = 0
|
775
957
|
row = 0
|
776
958
|
col = 1
|
@@ -786,5 +968,45 @@ module Minjs
|
|
786
968
|
end
|
787
969
|
return [row+1, col+1]
|
788
970
|
end
|
971
|
+
|
972
|
+
#
|
973
|
+
# position to line
|
974
|
+
#
|
975
|
+
def line(pos)
|
976
|
+
pos0 = pos1 = pos
|
977
|
+
while true
|
978
|
+
pos0 -= 1
|
979
|
+
break if line_terminator?(@codes[pos0])
|
980
|
+
end
|
981
|
+
pos0 += 1
|
982
|
+
|
983
|
+
while true
|
984
|
+
break if line_terminator?(@codes[pos1])
|
985
|
+
pos1 += 1
|
986
|
+
end
|
987
|
+
|
988
|
+
@codes[pos0..pos1].pack("U*")
|
989
|
+
end
|
990
|
+
|
991
|
+
def debug_str(pos = nil, row = nil, col = nil)
|
992
|
+
if pos.nil?
|
993
|
+
pos = @head_pos or @pos
|
994
|
+
end
|
995
|
+
|
996
|
+
t = ''
|
997
|
+
if col >= 80
|
998
|
+
t << @codes[(pos-80)..(pos+80)].pack("U*")
|
999
|
+
col = 81
|
1000
|
+
else
|
1001
|
+
t << line(pos)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
if col and col >= 1
|
1005
|
+
col = col - 1;
|
1006
|
+
end
|
1007
|
+
t << "\n"
|
1008
|
+
t << (' ' * col) + "^"
|
1009
|
+
t
|
1010
|
+
end
|
789
1011
|
end
|
790
1012
|
end
|