LibJS: Parse === and !== binary operators

This commit is contained in:
Conrad Pankoff 2020-03-12 23:11:33 +11:00 committed by Andreas Kling
parent 9d41aa4d5d
commit e88f2f15ee
Notes: sideshowbarker 2024-07-19 08:44:56 +09:00
4 changed files with 42 additions and 6 deletions

View file

@ -33,6 +33,7 @@
namespace JS {
HashMap<String, TokenType> Lexer::s_keywords;
HashMap<String, TokenType> Lexer::s_three_char_tokens;
HashMap<String, TokenType> Lexer::s_two_char_tokens;
HashMap<char, TokenType> Lexer::s_single_char_tokens;
@ -62,6 +63,11 @@ Lexer::Lexer(StringView source)
s_keywords.set("while", TokenType::While);
}
if (s_three_char_tokens.is_empty()) {
s_three_char_tokens.set("===", TokenType::EqualsEqualsEquals);
s_three_char_tokens.set("!==", TokenType::ExclamationMarkEqualsEquals);
}
if (s_two_char_tokens.is_empty()) {
s_two_char_tokens.set("+=", TokenType::PlusEquals);
s_two_char_tokens.set("-=", TokenType::MinusEquals);
@ -174,7 +180,7 @@ Token Lexer::next()
}
size_t value_start = m_position;
TokenType token_type;
auto token_type = TokenType::Invalid;
if (is_identifier_start()) {
// identifier or keyword
@ -205,8 +211,23 @@ Token Lexer::next()
} else if (m_current_char == EOF) {
token_type = TokenType::Eof;
} else {
bool found_three_char_token = false;
if (m_position+1 < m_source.length()) {
char secondChar = m_source[m_position];
char thirdChar = m_source[m_position+1];
char threeChars[] { (char)m_current_char, secondChar, thirdChar, 0 };
auto it = s_three_char_tokens.find(threeChars);
if (it != s_three_char_tokens.end()) {
found_three_char_token = true;
consume();
consume();
consume();
token_type = it->value;
}
}
bool found_two_char_token = false;
if (!is_eof()) {
if (!found_three_char_token && !is_eof()) {
char secondChar = m_source[m_position];
char twoChars[] { (char)m_current_char, secondChar, 0 };
auto it = s_two_char_tokens.find(twoChars);
@ -218,16 +239,20 @@ Token Lexer::next()
}
}
if (!found_two_char_token) {
bool found_one_char_token = false;
if (!found_three_char_token && !found_two_char_token) {
auto it = s_single_char_tokens.find(m_current_char);
if (it != s_single_char_tokens.end()) {
found_one_char_token = true;
consume();
token_type = it->value;
} else {
consume();
token_type = TokenType::Invalid;
}
}
if (!found_three_char_token && !found_two_char_token && !found_one_char_token) {
consume();
token_type = TokenType::Invalid;
}
}
m_current_token = Token(

View file

@ -54,6 +54,7 @@ private:
int m_current_char;
static HashMap<String, TokenType> s_keywords;
static HashMap<String, TokenType> s_three_char_tokens;
static HashMap<String, TokenType> s_two_char_tokens;
static HashMap<char, TokenType> s_single_char_tokens;
};

View file

@ -157,6 +157,12 @@ NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expre
case TokenType::LessThanEquals:
consume();
return make<BinaryExpression>(BinaryOp::LessThanEquals, move(lhs), parse_expression());
case TokenType::EqualsEqualsEquals:
consume();
return make<BinaryExpression>(BinaryOp::TypedEquals, move(lhs), parse_expression());
case TokenType::ExclamationMarkEqualsEquals:
consume();
return make<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression());
case TokenType::ParenOpen:
return parse_call_expression(move(lhs));
case TokenType::Equals:
@ -276,6 +282,8 @@ bool Parser::match_secondary_expression() const
|| type == TokenType::Slash
|| type == TokenType::SlashEquals
|| type == TokenType::Equals
|| type == TokenType::EqualsEqualsEquals
|| type == TokenType::ExclamationMarkEqualsEquals
|| type == TokenType::GreaterThan
|| type == TokenType::GreaterThanEquals
|| type == TokenType::LessThan

View file

@ -53,8 +53,10 @@ enum class TokenType {
Eof,
Equals,
EqualsEquals,
EqualsEqualsEquals,
ExclamationMark,
ExclamationMarkEquals,
ExclamationMarkEqualsEquals,
Finally,
Function,
GreaterThan,