Class: Minjs::Lex::Parser
- Inherits:
-
Object
- Object
- Minjs::Lex::Parser
- 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
Instance Attribute Summary collapse
-
#codes ⇒ Object
readonly
Returns the value of attribute codes.
-
#pos ⇒ Object
readonly
Returns the value of attribute pos.
Instance Method Summary collapse
-
#clear_cache ⇒ Object
clear cache of ECMA262 elements.
-
#comment ⇒ Object
Tests next literal is Comment or not.
-
#debug_str(pos = nil, row = 0, col = 0) ⇒ String
Returns string of input data around pos.
-
#div_punctuator ⇒ Object
Tests next literal is DivPunctuator or not.
-
#eof? ⇒ Boolean
Returns true if posision is at end of file.
-
#eql_lit?(l, hint = nil) ⇒ Boolean
check next literal is strictly equal to l or not.
-
#eql_lit_nolt?(l, hint = nil) ⇒ Boolean
check next literal is strictly equal to l or not.
-
#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>.
-
#fwd_after_peek ⇒ Object
Forwards position after calling peek_lit.
-
#fwd_lit(hint) ⇒ Object
fetch next literal.
-
#fwd_lit_nolt(hint) ⇒ Object
fetch next literal.
-
#identifier_name ⇒ Object
Tests next literal is IdentifierName or not.
-
#initialize(source_text = "", options = {}) ⇒ Parser
constructor
A new instance of Parser.
-
#line(pos) ⇒ Object
position to line.
-
#line_terminator ⇒ ECMA262::LineTerminator
Tests next literal is LineTerminator or not.
-
#match_lit?(l, hint = nil) ⇒ Boolean
check next literal is equal to l or not.
-
#match_lit_nolt?(l, hint = nil) ⇒ Boolean
check next literal is equal to l or not.
-
#multi_line_comment ⇒ Object
Tests next literal is MultiLineComment or not.
-
#next_input_element(hint) ⇒ Object
Fetch next literal and forward position.
-
#numeric_literal ⇒ ECMA262::ECMA262Numeric
Tests next literal is NumericLiteral or not.
-
#peek_lit(hint) ⇒ Object
fetch next literal.
-
#peek_lit_nolt(hint) ⇒ Object
fetch next literal.
-
#punctuator ⇒ Object
Tests next literal is Punctuator or not.
-
#regexp_literal ⇒ ECMA262::RegExp
Tests next literal is RegExp or not.
-
#row_col(pos) ⇒ Object
position to [row, col].
-
#single_line_comment ⇒ Object
Tests next literal is SinleLineComment or not.
-
#string_literal ⇒ ECMA262::ECMA262String
Tests next literal is StringLiteral or not.
-
#token ⇒ Object
Tests next literal is Token or not.
-
#white_space ⇒ ECMA262::WhiteSpace
Tests next literal is WhiteSpace or not.
Methods included from Function
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
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.
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/minjs/lex/parser.rb', line 23 def initialize(source_text = "", = {}) 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 = [:logger] @eval_nest = 0 end |
Instance Attribute Details
#codes ⇒ Object (readonly)
Returns the value of attribute codes.
19 20 21 |
# File 'lib/minjs/lex/parser.rb', line 19 def codes @codes end |
#pos ⇒ Object (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_cache ⇒ Object
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 |
#comment ⇒ Object
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.
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
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_punctuator ⇒ Object
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.
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
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
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
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_peek ⇒ Object
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_name ⇒ Object
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.
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_terminator ⇒ ECMA262::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.
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
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
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_comment ⇒ Object
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.
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.
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_literal ⇒ ECMA262::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.
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 |
#punctuator ⇒ Object
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.
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_literal ⇒ ECMA262::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.
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_comment ⇒ Object
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.
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_literal ⇒ ECMA262::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.
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 |
#token ⇒ Object
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.
228 229 230 |
# File 'lib/minjs/lex/parser.rb', line 228 def token identifier_name || numeric_literal || punctuator || string_literal end |
#white_space ⇒ ECMA262::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.
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 |