from: https://v8.dev/blog/scanner
v8 Scanner
v8 이 소스를 파싱해서 AST 로 만든다.abstract syntax tree (AST)이걸로 프로그램 구조를 표현한다.
v8은 complile 해야 프로그램을 실행할 수 있다.
v8 parser 은 scanner 에서 만들어놓은 token 을 소모한다.
이때 scanner 가 사용하는 character stream의 encoding 은 utf16만 지원한다.
scanner 에 input 으로 제공하기 전에 이전에 모든 encoding 을 utf16으로 convert 하는 과정을 거친다.
scanner는 이 utf16을 decode 해서 unicode 로 만들어서 사용한다.
이 decoded character 들을 이제 가져다 scanner 가 token 을 만든다.
2개의 token 사이에 whitespace 가 있으면 거기에 ;(semicolon)을 넣는다.( WhitespaceECMAScript® 2020 Language Specification > Auto semicolon insertion)
다음 token 을 scan 하기 전까지 모든 whitespace는 skip 된다.(newline 이 발생하는지 추적하면서)
real world 에서는 대체로 js 들이 minified 돼서 여러개의 whitespace 가 연속해서 나타나는 경우가 드물다.
그래서 V8 은 whitespace 도 하나의 token 으로 취급한다. (Token::WHITESPACE) 그래서 '//' 같이 comment 가 오는 경우에도 Token::WHITESPACE 를 return 해 버린다. 그러면 paring 하는 loop 에서 다른 Token이 나올때 까지 계속 scan 을 이어나갈 수 있게 된다.
(역주: 다시 말하면, // 가 나와서 이것을 다른 token 으로 정의(Token::COMMENT) 등으로 정의해서 사용하게 되면, loop 을 한번 벗어난 후에 다시 parsing 을 시작해야 하지만, 이것을 whitespace 와 같은 속성으로 취급해 버리면, 이 overhead 를 없앨 수 있게 되는 것이다.)
V8_INLINE Token::Value Scanner::ScanSingleToken() { Token::Value token; do { next().location.beg_pos = source_pos(); if (V8_LIKELY(static_cast<unsigned>(c0_) <= kMaxAscii)) { token = one_char_tokens[c0_]; switch (token) { ... case Token::DIV: // / // /* /= Advance(); if (c0_ == '/') { uc32 c = Peek(); if (c == '#' || c == '@') { Advance(); Advance(); token = SkipSourceURLComment(); continue; } token = SkipSingleLineComment(); continue; } if (c0_ == '*') { token = SkipMultiLineComment(); continue; } if (c0_ == '=') return Select(Token::ASSIGN_DIV); return Token::DIV; ... case Token::WHITESPACE: token = SkipWhiteSpace(); continue; case Token::NUMBER: return ScanNumber(false); case Token::IDENTIFIER: return ScanIdentifierOrKeyword(); default: UNREACHABLE(); } } if (IsIdentifierStart(c0_) || (CombineSurrogatePair() && IsIdentifierStart(c0_))) { return ScanIdentifierOrKeyword(); } if (c0_ == kEndOfInput) { return source_->has_parser_error() ? Token::ILLEGAL : Token::EOS; } token = SkipWhiteSpace(); // Continue scanning for tokens as long as we're just skipping whitespace. } while (token == Token::WHITESPACE); return token; }
Identifier scanning
Internalizing minified identifiers
Keywords
Surrogate pairs
AdvanceUntil
댓글 없음:
댓글 쓰기