Class: Minjs::Lex::Parser

Inherits:
Object
  • Object
show all
Includes:
Minjs, Ctype, Expression, Function, Program, Statement
Defined in:
lib/minjs/lex/parser.rb

Overview

ECMA262 Parser class

This class parses ECMA262 script languageā€™s source text and convers it to elements (ECMA262::Base).

Constant Summary

Constants included from Minjs

VERSION

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Function

#func_declaration, #func_exp

Methods included from Expression

#additive_exp, #arguments, #array_literal, #assignment_exp, #bitwise_and_exp, #bitwise_or_exp, #bitwise_xor_exp, #call_exp, #cond_exp, #equality_exp, #exp, #identifier, #left_hand_side_exp, #literal, #logical_and_exp, #logical_or_exp, #member_exp, #multiplicative_exp, #new_exp, #object_literal, #postfix_exp, #primary_exp, #property_name, #property_name_and_value_list, #property_set_parameter_list, #relational_exp, #shift_exp, #unary_exp

Methods included from Statement

#block, #break_statement, #continue_statement, #debugger_statement, #empty_statement, #exp_statement, #if_statement, #iteration_statement, #labelled_statement, #return_statement, #semicolon, #statement, #switch_statement, #throw_statement, #try_statement, #var_statement, #with_statement

Methods included from Program

#program, #source_elements

Methods included from Ctype

#decimal_digit?, #hex_digit?, #identifier_part?, #identifier_start?, #idname?, #line_terminator?, #octal_digit?, #white_space?

Constructor Details

#initialize(source_text = "", options = {}) ⇒ Parser

Returns a new instance of Parser.

Parameters:

  • source_text (String) (defaults to: "")

    input source text

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :logger (Logger)

    logger for debug



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/minjs/lex/parser.rb', line 23

def initialize(source_text = "", options = {})
  source_text = source_text.gsub(/\r\n/, "\n")
  @codes = source_text.codepoints
  if !source_text.match(/\n\z/)
    @codes.push(10)
  end
  @pos = 0
  clear_cache
  @logger = options[:logger]

  @eval_nest = 0
end

Instance Attribute Details

#codesObject (readonly)

Returns the value of attribute codes.



19
20
21
# File 'lib/minjs/lex/parser.rb', line 19

def codes
  @codes
end

#posObject (readonly)

Returns the value of attribute pos.



18
19
20
# File 'lib/minjs/lex/parser.rb', line 18

def pos
  @pos
end

Instance Method Details

#clear_cacheObject

clear cache of ECMA262 elements



37
38
39
40
# File 'lib/minjs/lex/parser.rb', line 37

def clear_cache
  @lit_cache = {}
  @lit_nextpos = {}
end

#commentObject

Tests next literal is Comment or not.

If literal is Comment return ECMA262::MultiLineComment or SingeLineComment object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



169
170
171
# File 'lib/minjs/lex/parser.rb', line 169

def comment
  multi_line_comment || single_line_comment
end

#debug_str(pos = nil, row = 0, col = 0) ⇒ String

Returns string of input data around pos

Parameters:

  • pos (defaults to: nil)

    position

  • row (defaults to: 0)

    row

  • col (defaults to: 0)

    column

Returns:

  • (String)

    string



1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
# File 'lib/minjs/lex/parser.rb', line 1121

def debug_str(pos = nil, row = 0, col = 0)
  if pos.nil?
    pos = @head_pos or @pos
  end

  t = ''
  if col >= 80
    t << @codes[(pos-80)..(pos+80)].pack("U*")
    col = 81
  else
    t << line(pos)
  end

  if col and col >= 1
    col = col - 1;
  end
  t << "\n"
  t << (' ' * col) + "^"
  t
end

#div_punctuatorObject

Tests next literal is DivPunctuator or not.

If literal is DivPunctuator return ECMA262::PUNC_DIV or ECMA262::PUNC_DIVASSIGN object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/minjs/lex/parser.rb', line 474

def div_punctuator
  if @codes[@pos] == 0x2f
    if @codes[@pos+1] == 0x3d
      @pos += 2
      return ECMA262::PUNC_DIVASSIGN
    else
      @pos += 1
      return ECMA262::PUNC_DIV
    end
  end
  nil
end

#eof?Boolean

Returns true if posision is at end of file

Returns:

  • (Boolean)


920
921
922
# File 'lib/minjs/lex/parser.rb', line 920

def eof?
  peek_lit(nil).nil?
end

#eql_lit?(l, hint = nil) ⇒ Boolean

check next literal is strictly equal to l or not. white spaces and line terminators are skipped and ignored.

if next literal is not l, position is not forwarded if next literal is l, position is forwarded

Returns:

  • (Boolean)


931
932
933
934
935
936
937
938
939
# File 'lib/minjs/lex/parser.rb', line 931

def eql_lit?(l, hint = nil)
  lit = peek_lit(hint)
  if lit.eql? l
    fwd_after_peek
    lit
  else
    nil
  end
end

#eql_lit_nolt?(l, hint = nil) ⇒ Boolean

check next literal is strictly equal to l or not. white spaces are skipped and ignored. line terminators are not ignored.

if next literal is not l, position is not forwarded if next literal is l, position is forwarded

Returns:

  • (Boolean)


949
950
951
952
953
954
955
956
957
# File 'lib/minjs/lex/parser.rb', line 949

def eql_lit_nolt?(l, hint = nil)
  lit = peek_lit_nolt(hint)
  if lit.eql? l
    fwd_after_peek
    lit
  else
    nil
  end
end

#eval_lit(&block) ⇒ Object

break <val> => position is rewind, then break with <val> return <val> => position is rewind, then return <val> next <val> => position is not rewind, then break with <val>



1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
# File 'lib/minjs/lex/parser.rb', line 1056

def eval_lit(&block)
  begin
    saved_pos = @pos
    @eval_nest += 1
    ret = yield
  ensure
    @eval_nest -= 1
    if ret.nil?
      @pos = saved_pos
      nil
    else
      if @eval_nest == 0
        #STDERR.puts "clear_cache [#{saved_pos}..#{@pos}]"
        clear_cache
      end
    end
  end
end

#fwd_after_peekObject

Forwards position after calling peek_lit.

This method quickly forward position after calling peek_lit.



1024
1025
1026
# File 'lib/minjs/lex/parser.rb', line 1024

def fwd_after_peek
  @pos = @head_pos
end

#fwd_lit(hint) ⇒ Object

fetch next literal. position is forwarded. white spaces and line terminators are skipped and ignored.



1033
1034
1035
1036
1037
# File 'lib/minjs/lex/parser.rb', line 1033

def fwd_lit(hint)
  while lit = next_input_element(hint) and (lit.ws? or lit.lt?)
  end
  lit
end

#fwd_lit_nolt(hint) ⇒ Object

fetch next literal. position is forwarded. white spaces are skipped and ignored. line terminators are not ignored.



1045
1046
1047
1048
1049
# File 'lib/minjs/lex/parser.rb', line 1045

def fwd_lit_nolt(hint)
  while lit = next_input_element(hint) and lit.ws?
  end
  lit
end

#identifier_nameObject

Tests next literal is IdentifierName or not

If literal is IdentifierName return ECMA262::IdentifierName object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/minjs/lex/parser.rb', line 257

def identifier_name
  return nil if (code = @codes[@pos]).nil?

  pos0 = @pos
  chars = []
  if code == 0x5c and ucode = unicode_escape? and identifier_start?(ucode)
    chars.push(ucode)
    @pos += 6
  elsif identifier_start?(code)
    chars.push(code)
    @pos += 1
  else
    return nil
  end

  while true
    code = @codes[@pos]
    if code == 0x5c and ucode = unicode_escape? and identifier_part?(ucode)
      chars.push(ucode)
      @pos += 6
    elsif identifier_part?(code)
      chars.push(code)
      @pos += 1
    else
      name = chars.pack("U*").to_sym
      return ECMA262::IdentifierName.get(name)
    end
  end
end

#line(pos) ⇒ Object

position to line



1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
# File 'lib/minjs/lex/parser.rb', line 1098

def line(pos)
  pos0 = pos1 = pos
  while true
    pos0 -= 1
    break if line_terminator?(@codes[pos0])
  end
  pos0 += 1

  while true
    break if line_terminator?(@codes[pos1])
    pos1 += 1
  end

  @codes[pos0..pos1].pack("U*")
end

#line_terminatorECMA262::LineTerminator

Tests next literal is LineTerminator or not.

If literal is LineTerminator return ECMA262::LineTerminator object and forward lexical parser position. Otherwise return nil and position is not changed.

Even if next literal is sequence of two or more line terminators, this method returns only one line terminator.

Returns:

See Also:



150
151
152
153
154
155
156
157
158
159
# File 'lib/minjs/lex/parser.rb', line 150

def line_terminator
  if line_terminator?(@codes[@pos])
    begin
      @pos += 1
    end until !line_terminator?(@codes[@pos])
    return ECMA262::LineTerminator.get
  else
    nil
  end
end

#match_lit?(l, hint = nil) ⇒ Boolean

check next literal is equal to l or not. white spaces and line terminators are skipped and ignored.

if next literal is not l, position is not forwarded if next literal is l, position is forwarded

Returns:

  • (Boolean)


966
967
968
969
970
971
972
973
974
# File 'lib/minjs/lex/parser.rb', line 966

def match_lit?(l, hint = nil)
  lit = peek_lit(hint)
  if lit == l
    fwd_after_peek
    lit
  else
    nil
  end
end

#match_lit_nolt?(l, hint = nil) ⇒ Boolean

check next literal is equal to l or not. white spaces are skipped and ignored. line terminators are not ignored.

if next literal is not l, position is not forwarded if next literal is l, position is forwarded

Returns:

  • (Boolean)


984
985
986
987
988
989
990
991
992
# File 'lib/minjs/lex/parser.rb', line 984

def match_lit_nolt?(l, hint = nil)
  lit = peek_lit_nolt(hint)
  if lit == l
    fwd_after_peek
    lit
  else
    nil
  end
end

#multi_line_commentObject

Tests next literal is MultiLineComment or not.

If literal is MultiLineComment return ECMA262::MultiLineComment object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/minjs/lex/parser.rb', line 181

def multi_line_comment
  # /*
  if @codes[@pos] == 0x2f and @codes[@pos + 1] == 0x2a
    @pos += 2
    pos0 = @pos
    # */
    while (code = @codes[@pos] != 0x2a) or @codes[@pos + 1] != 0x2f
      raise ParseError.new("no `*/' at end of comment", self) if code.nil?
      @pos += 1
    end
    @pos +=2
    return ECMA262::MultiLineComment.new(@codes[pos0...(@pos-2)].pack("U*"))
  else
    nil
  end
end

#next_input_element(hint) ⇒ Object

Fetch next literal and forward position.

Parameters:

  • hint (Symbol)

    hint of parsing. The hint must be one of the :regexp, :div, nil The hint parameter is used to determine next literal is division-mark or regular expression. because ECMA262 says:

    There are no syntactic grammar contexts where both a leading division or division-assignment, and a leading RegularExpressionLiteral are permitted. This is not affected by semicolon insertion (see 7.9); in examples such as the following: To determine ā€˜/ā€™ is regular expression or not



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/minjs/lex/parser.rb', line 54

def next_input_element(hint)
  if ret = @lit_cache[@pos]
    @pos = @lit_nextpos[@pos]
    @head_pos = @pos
    return ret
  end
  pos0 = @pos
  #
  # skip white space here, because ECMA262(5.1.2) says:
  #
  #   Simple white space and single-line comments are discarded and
  #   do not appear in the stream of input elements for the
  #   syntactic grammar.
  #
  while white_space or single_line_comment
  end

  ret = line_terminator || multi_line_comment || token
  if ret
    @lit_cache[pos0] = ret
    @lit_nextpos[pos0] = @pos
    @head_pos = @pos
    return ret
  end

  if @codes[@pos].nil?
    return nil
  end
  if hint.nil?
    if @codes[@pos] == 0x2f
      ECMA262::LIT_DIV_OR_REGEXP_LITERAL
    else
      nil
    end
  elsif hint == :div
    ret = div_punctuator
    if ret
      @lit_cache[pos0] = ret
      @lit_nextpos[pos0] = @pos
    end
    @head_pos = @pos
    return ret
  elsif hint == :regexp
    ret = regexp_literal
    if ret
      @lit_cache[pos0] = ret
      @lit_nextpos[pos0] = @pos
    end
    @head_pos = @pos
    return ret
  else
    if @codes[@pos] == 0x2f
      ECMA262::LIT_DIV_OR_REGEXP_LITERAL
    else
      nil
    end
  end
end

#numeric_literalECMA262::ECMA262Numeric

Tests next literal is NumericLiteral or not.

If literal is NumericLiteral return ECMA262::ECMA262Numeric object and forward lexical parser position. Otherwise return nil and position is not changed.

Returns:

See Also:



580
581
582
# File 'lib/minjs/lex/parser.rb', line 580

def numeric_literal
  hex_integer_literal || octal_integer_literal || decimal_literal
end

#peek_lit(hint) ⇒ Object

fetch next literal. position is not forwarded. white spaces and line terminators are skipped and ignored.



999
1000
1001
1002
1003
1004
1005
# File 'lib/minjs/lex/parser.rb', line 999

def peek_lit(hint)
  pos0 = @pos
  while lit = next_input_element(hint) and (lit.ws? or lit.lt?)
  end
  @pos = pos0
  lit
end

#peek_lit_nolt(hint) ⇒ Object

fetch next literal.

position is not forwarded. white spaces are skipped and ignored. line terminators are not ignored.



1013
1014
1015
1016
1017
1018
1019
# File 'lib/minjs/lex/parser.rb', line 1013

def peek_lit_nolt(hint)
  pos0 = @pos
  while lit = next_input_element(hint) and lit.ws?
  end
  @pos = pos0
  lit
end

#punctuatorObject

Tests next literal is Punctuator or not

If literal is Punctuator return ECMA262::Punctuator object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
# File 'lib/minjs/lex/parser.rb', line 295

def punctuator
  code0 = @codes[@pos]
  code1 = @codes[@pos+1]
  code2 = @codes[@pos+2]
  code3 = @codes[@pos+3]
  if false
  elsif code0 == 0x28 # (
    @pos += 1 # (
    return ECMA262::PUNC_LPARENTHESIS
  elsif code0 == 0x29 # )
    @pos += 1 # )
    return ECMA262::PUNC_RPARENTHESIS
  elsif code0 == 0x7b # {
    @pos += 1 # {
    return ECMA262::PUNC_LCURLYBRAC
  elsif code0 == 0x7d # }
    @pos += 1 # }
    return ECMA262::PUNC_RCURLYBRAC
  elsif code0 == 0x3b # ;
    @pos += 1 # ;
    return ECMA262::PUNC_SEMICOLON
  elsif code0 == 0x3d # =
    if code1 == 0x3d and code2 == 0x3d # ===
      @pos += 3
      return ECMA262::PUNC_SEQ
    end
    if code1 == 0x3d # ==
      @pos += 2
      return ECMA262::PUNC_EQ
    end
    @pos += 1 # =
    return ECMA262::PUNC_ASSIGN
  elsif code0 == 0x21 # !
    if code1 == 0x3d and code2 == 0x3d # !==
      @pos += 3
      return ECMA262::PUNC_SNEQ
    end
    if code1 == 0x3d # !=
      @pos += 2
      return ECMA262::PUNC_NEQ
    end
    @pos += 1 # !
    return ECMA262::PUNC_LNOT
  elsif code0 == 0x25 # %
    if code1 == 0x3d # %=
      @pos += 2
      return ECMA262::PUNC_MODASSIGN
    end
    @pos += 1 # %
    return ECMA262::PUNC_MOD
  elsif code0 == 0x26 # &
    if code1 == 0x3d # &=
      @pos += 2
      return ECMA262::PUNC_ANDASSIGN
    end
    if code1 == 0x26 # &&
      @pos += 2
      return ECMA262::PUNC_LAND
    end
    @pos += 1 # &
    return ECMA262::PUNC_AND
  elsif code0 == 0x2a # *
    if code1 == 0x3d # *=
      @pos += 2
      return ECMA262::PUNC_MULASSIGN
    end
    @pos += 1 # *
    return ECMA262::PUNC_MUL
  elsif code0 == 0x2b # +
    if code1 == 0x3d # +=
      @pos += 2
      return ECMA262::PUNC_ADDASSIGN
    end
    if code1 == 0x2b # ++
      @pos += 2
      return ECMA262::PUNC_INC
    end
    @pos += 1 # +
    return ECMA262::PUNC_ADD
  elsif code0 == 0x2c # ,
    @pos += 1 # ,
    return ECMA262::PUNC_COMMA
  elsif code0 == 0x2d # -
    if code1 == 0x3d # -=
      @pos += 2
      return ECMA262::PUNC_SUBASSIGN
    end
    if code1 == 0x2d # --
      @pos += 2
      return ECMA262::PUNC_DEC
    end
    @pos += 1 # -
    return ECMA262::PUNC_SUB
  elsif code0 == 0x2e # .
    @pos += 1 # .
    return ECMA262::PUNC_PERIOD
  elsif code0 == 0x3a # :
    @pos += 1 # :
    return ECMA262::PUNC_COLON
  elsif code0 == 0x3c # <
    if code1 == 0x3d # <=
      @pos += 2
      return ECMA262::PUNC_LTEQ
    end
    if code1 == 0x3c and code2 == 0x3d # <<=
      @pos += 3
      return ECMA262::PUNC_LSHIFTASSIGN
    end
    if code1 == 0x3c # <<
      @pos += 2
      return ECMA262::PUNC_LSHIFT
    end
    @pos += 1 # <
    return ECMA262::PUNC_LT
  elsif code0 == 0x3e # >
    if code1 == 0x3e and code2 == 0x3e and code3 == 0x3d # >>>=
      @pos += 4
      return ECMA262::PUNC_URSHIFTASSIGN
    end
    if code1 == 0x3e and code2 == 0x3e # >>>
      @pos += 3
      return ECMA262::PUNC_URSHIFT
    end
    if code1 == 0x3e and code2 == 0x3d # >>=
      @pos += 3
      return ECMA262::PUNC_RSHIFTASSIGN
    end
    if code1 == 0x3e # >>
      @pos += 2
      return ECMA262::PUNC_RSHIFT
    end
    if code1 == 0x3d # >=
      @pos += 2
      return ECMA262::PUNC_GTEQ
    end
    @pos += 1 # >
    return ECMA262::PUNC_GT
  elsif code0 == 0x3f # ?
    @pos += 1 # ?
    return ECMA262::PUNC_CONDIF
  elsif code0 == 0x5b # [
    @pos += 1 # [
    return ECMA262::PUNC_LSQBRAC
  elsif code0 == 0x5d # ]
    @pos += 1 # ]
    return ECMA262::PUNC_RSQBRAC
  elsif code0 == 0x5e # ^
    if code1 == 0x3d # ^=
      @pos += 2
      return ECMA262::PUNC_XORASSIGN
    end
    @pos += 1 # ^
    return ECMA262::PUNC_XOR
  elsif code0 == 0x7c # |
    if code1 == 0x7c # ||
      @pos += 2
      return ECMA262::PUNC_LOR
    end
    if code1 == 0x3d # |=
      @pos += 2
      return ECMA262::PUNC_ORASSIGN
    end
    @pos += 1 # |
    return ECMA262::PUNC_OR
  elsif code0 == 0x7e # ~
    @pos += 1 # ~
    return ECMA262::PUNC_NOT
  end
  nil
end

#regexp_literalECMA262::RegExp

Tests next literal is RegExp or not.

If literal is RegExp return ECMA262::ECMA262RegExp object and forward lexical parser position. Otherwise return nil and position is not changed.

Returns:

  • (ECMA262::RegExp)

See Also:



496
497
498
499
500
501
502
503
504
505
# File 'lib/minjs/lex/parser.rb', line 496

def regexp_literal
  # RegularExpressionLiteral::
  # 	/ RegularExpressionBody / RegularExpressionFlags
  pos0 = @pos
  return nil unless @codes[@pos] == 0x2f

  body = regexp_body
  flags = regexp_flags
  return ECMA262::ECMA262RegExp.new(body, flags)
end

#row_col(pos) ⇒ Object

position to [row, col]



1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
# File 'lib/minjs/lex/parser.rb', line 1078

def row_col(pos)
  _pos = 0
  row = 0
  col = 1
  @codes.each do |code|
    break if _pos >= pos
    if line_terminator?(code)
      row += 1
      col = 0
    else
      col += 1
    end
    _pos += 1
  end
  return [row+1, col+1]
end

#single_line_commentObject

Tests next literal is SinleLineComment or not.

If literal is SingleLineComment return ECMA262::SingleLineComment object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/minjs/lex/parser.rb', line 206

def single_line_comment
  # //
  if @codes[@pos] == 0x2f and @codes[@pos + 1] == 0x2f
    @pos += 2
    pos0 = @pos
    while (code = @codes[@pos]) and !line_terminator?(code)
      @pos += 1
    end
    return ECMA262::SingleLineComment.new(@codes[pos0...@pos].pack("U*"))
  else
    nil
  end
end

#string_literalECMA262::ECMA262String

Tests next literal is StringLiteral or not.

If literal is StringLiteral return ECMA262::ECMA262String object and forward lexical parser position. Otherwise return nil and position is not changed.

Returns:

See Also:



760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
# File 'lib/minjs/lex/parser.rb', line 760

def string_literal
  # StringLiteral ::
  # " DoubleStringCharactersopt "
  # ' SingleStringCharactersopt '
  #
  # DoubleStringCharacters ::
  # DoubleStringCharacter DoubleStringCharactersopt
  #
  # SingleStringCharacters ::
  # SingleStringCharacter SingleStringCharactersopt
  #
  # DoubleStringCharacter ::
  # SourceCharacter but not one of " or \ or LineTerminator
  # \ EscapeSequence
  # LineContinuation
  #
  # SingleStringCharacter ::
  # SourceCharacter but not one of ' or \ or LineTerminator
  # \ EscapeSequence
  # LineContinuation
  #
  if (code = @codes[@pos]) == 0x27 #'
    term = 0x27
  elsif code == 0x22 #"
    term = 0x22
  else
    return nil
  end
  @pos += 1
  pos0 = @pos

  str = []
  while (code = @codes[@pos])
    if code.nil?
      raise ParseError.new("no `#{term}' at end of string", self)
    elsif line_terminator?(code)
      raise ParseError.new("string has line terminator in body", self)
    elsif code == 0x5c #\
      @pos += 1
      str.push(escape_sequence)
    elsif code == term
      @pos += 1
      return ECMA262::ECMA262String.new(str.compact.pack("U*"))
    else
      @pos += 1
      str.push(code)
    end
  end
  nil
end

#tokenObject

Tests next literal is Token or not

If literal is Token return ECMA262::Base object and forward lexical parser position. Otherwise return nil and position is not changed.

See Also:



228
229
230
# File 'lib/minjs/lex/parser.rb', line 228

def token
  identifier_name || numeric_literal || punctuator || string_literal
end

#white_spaceECMA262::WhiteSpace

Tests next literal is WhiteSpace or not.

If literal is WhiteSpace return ECMA262::WhiteSpace object and forward lexical parser position. Otherwise return nil and position is not changed.

Even if next literal is sequence of two or more white spaces, this method returns only one white space.

Returns:

See Also:



126
127
128
129
130
131
132
133
134
135
# File 'lib/minjs/lex/parser.rb', line 126

def white_space
  if white_space?(@codes[@pos])
    begin
      @pos += 1
    end until !white_space?(@codes[@pos])
    return ECMA262::WhiteSpace.get
  else
    nil
  end
end