lib/minjs/lex.rb in minjs-0.1.2 vs lib/minjs/lex.rb in minjs-0.1.3
- old
+ new
@@ -113,11 +113,11 @@
@pos = @pos + 2
pos0 = @pos
lf = false
while (@codes[@pos] != 0x2a or @codes[@pos + 1] != 0x2f)
if @codes[@pos].nil?
- raise ParseError.new("no `*/' at end of comment")
+ raise ParseError.new("no `*/' at end of comment", self)
end
if line_terminator?(@codes[@pos])
lf = true
end
@pos = @pos + 1
@@ -157,25 +157,48 @@
@lit_nextpos[pos0] = @pos
end
ret
end
+ def unicode_escape?
+ if @codes[@pos] == 0x5c and
+ @codes[@pos+1] == 0x75 and
+ hex_number?(@codes[@pos+2]) and
+ hex_number?(@codes[@pos+3]) and
+ hex_number?(@codes[@pos+4]) and
+ hex_number?(@codes[@pos+5])
+ [@codes[@pos+2],@codes[@pos+3],@codes[@pos+4],@codes[@pos+5]].pack("U*").to_i(16)
+ else
+ false
+ end
+ end
+
def identifier_name
pos0 = @pos
- code = @codes[@pos]
- return nil if code.nil?
- if identifier_start?(code)
- while true
+ return nil if @codes[@pos].nil?
+
+ chars = []
+ if u=unicode_escape? and identifier_start?(u)
+ chars.push(u)
+ @pos += 6
+ elsif identifier_start?(@codes[@pos])
+ chars.push(@codes[@pos])
+ @pos += 1
+ else
+ return nil
+ end
+
+ while true
+ code = @codes[@pos]
+ if u=unicode_escape? and (identifier_start?(u) || identifier_part?(u))
+ chars.push(u)
+ @pos += 6
+ elsif identifier_part?(@codes[@pos])
+ chars.push(@codes[@pos])
@pos += 1
- code = @codes[@pos]
- if code.nil?
- break
- elsif identifier_part?(code)
- ;#
- else
- return ECMA262::IdentifierName.new(nil, @codes[pos0...@pos].pack("U*").to_sym)
- end
+ else
+ return ECMA262::IdentifierName.new(nil, chars.pack("U*").to_sym)
end
end
end
def punctuator
@@ -357,26 +380,26 @@
return ECMA262::ECMA262RegExp.new(body, flags)
end
def regexp_body
if @codes[@pos] == 0x2a
- raise ParseError.new("first character of regular expression is `*'")
+ raise ParseError.new("first character of regular expression is `*'", self)
end
pos0 = @pos
@pos += 1
while !(@codes[@pos] == 0x2f)
if @codes[@pos].nil?
- raise ParseError.new("no `/' end of regular expression")
+ raise ParseError.new("no `/' end of regular expression", self)
end
if line_terminator?(@codes[@pos])
debug_lit
- raise ParseError.new("regular expression has line terminator in body")
+ raise ParseError.new("regular expression has line terminator in body", self)
end
if @codes[@pos] == 0x5c # \
@pos += 1
if line_terminator?(@codes[@pos])
- raise ParseError.new("regular expression has line terminator in body")
+ raise ParseError.new("regular expression has line terminator in body", self)
end
@pos += 1
elsif @codes[@pos] == 0x5b # [
regexp_class
else
@@ -387,24 +410,24 @@
return @codes[(pos0+1)...(@pos-1)].pack("U*")
end
def regexp_class
if @codes[@pos] != 0x5b
- raise ParseError.new('bad regular expression')
+ raise ParseError.new('bad regular expression', self)
end
@pos += 1
while !(@codes[@pos] == 0x5d)
if @codes[@pos].nil?
- raise ParseError.new("no `]' end of regular expression class")
+ raise ParseError.new("no `]' end of regular expression class", self)
end
if line_terminator?(@codes[@pos])
- raise ParseError.new("regular expression has line terminator in body")
+ raise ParseError.new("regular expression has line terminator in body", self)
end
if @codes[@pos] == 0x5c # \
@pos += 1
if line_terminator?(@codes[@pos])
- raise ParseError.new("regular expression has line terminator in body")
+ raise ParseError.new("regular expression has line terminator in body", self)
end
@pos += 1
else
@pos += 1
end
@@ -435,13 +458,15 @@
if code == 0x30 and (@codes[@pos+1] == 0x78 || @codes[@pos+1] == 0x58) #hex integer
@pos += 2
while true
code = @codes[@pos]
if (code >= 0x30 and code <= 0x39) || (code >= 0x41 and code <= 0x4f) || (code >= 0x61 and code <= 0x6f)
+ ;
+ elsif identifier_start?(code)
+ raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
else
- raw = @codes[pos0...@pos].pack("U*")
- return ECMA262::ECMA262Numeric.new(raw, @codes[(pos0+2)...@pos].pack("U*").to_i(16))
+ return ECMA262::ECMA262Numeric.new(@codes[(pos0+2)...@pos].pack("U*").to_i(16))
end
@pos += 1
end
else
nil
@@ -460,42 +485,49 @@
end
if @codes[@pos] == 0x65 || @codes[@pos] == 0x45
@pos += 1
e = exp_part
end
- raw = @codes[pos0...@pos].pack("U*")
- return ECMA262::ECMA262Numeric.new(raw, 0, f, e)
- else
- nil
+ if identifier_start?(@codes[@pos])
+ raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
+ end
+
+ return ECMA262::ECMA262Numeric.new(0, f, e)
end
+
if code >= 0x30 and code <= 0x39
i = decimal_digits
- if @codes[@pos] == 0x2e
+ if @codes[@pos] == 0x2e #.
@pos += 1
f = decimal_digits
- if @codes[@pos] == 0x65 || @codes[@pos] == 0x45
+ if @codes[@pos] == 0x65 || @codes[@pos] == 0x45 #e or E
@pos += 1
e = exp_part
end
- elsif @codes[@pos] == 0x65 || @codes[@pos] == 0x45
+ elsif @codes[@pos] == 0x65 || @codes[@pos] == 0x45 #e or E
@pos += 1
e = exp_part
end
- raw = @codes[pos0...@pos].pack("U*")
- return ECMA262::ECMA262Numeric.new(raw, i, f, e)
+ if identifier_start?(@codes[@pos])
+ raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
+ end
+
+ return ECMA262::ECMA262Numeric.new(i, f, e)
end
+
+ nil
end
def exp_part
if @codes[@pos] == 0x2b
@pos += 1
elsif @codes[@pos] == 0x2d
@pos += 1
neg = true
end
if neg
- e = -decimal_digits
+ e = "-#{decimal_digits}"
else
e = decimal_digits
end
e
end
@@ -508,11 +540,11 @@
while true
code = @codes[@pos]
if code >= 0x30 and code <= 0x39
@pos += 1
else
- return @codes[pos0...@pos].pack("U*").to_i
+ return @codes[pos0...@pos].pack("U*")
end
end
else
nil
end
@@ -534,13 +566,13 @@
str = ''
while @codes[@pos]
@pos += 1
code = @codes[@pos]
if code.nil?
- raise ParseError.new("no `#{term}' at end of string")
+ raise ParseError.new("no `#{term}' at end of string", self)
elsif line_terminator?(code)
- raise ParseError.new("string has line terminator in body")
+ raise ParseError.new("string has line terminator in body", self)
elsif code == 0x5c #\
@pos += 1
str << esc_string
elsif code == term
@pos += 1
@@ -738,8 +770,25 @@
#@error_pos = @pos
@pos = saved_pos
nil
end
end
+ end
+
+ def line_col(pos)
+ _pos = 0
+ row = 0
+ col = 1
+ @codes.each do |code|
+ break if _pos >= pos
+ if line_terminator?(code)
+ row += 1
+ row = 0
+ else
+ col += 1
+ end
+ _pos += 1
+ end
+ return [row+1, col]
end
end
end