1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 17:55:07 +00:00

LibJS: Lex single quote strings, escaped chars and unterminated strings

This commit is contained in:
Stephan Unverwerth 2020-03-14 11:45:25 +01:00 committed by Andreas Kling
parent d439013903
commit c0e6234219
5 changed files with 33 additions and 4 deletions

View file

@ -0,0 +1,7 @@
var d = "Double quoted string";
var s = 'Single quoted string';
var e = "Escaped characters \n \" \t \\"
var u = "Unterminated string
this is not possible in js"
var u2 = 'This is neither

View file

@ -169,6 +169,12 @@ bool Lexer::is_block_comment_end() const
return m_current_char == '*' && m_position < m_source.length() && m_source[m_position] == '/'; return m_current_char == '*' && m_position < m_source.length() && m_source[m_position] == '/';
} }
void Lexer::syntax_error(const char* msg)
{
m_has_errors = true;
fprintf(stderr, "Syntax Error: %s\n", msg);
}
Token Lexer::next() Token Lexer::next()
{ {
size_t trivia_start = m_position; size_t trivia_start = m_position;
@ -218,13 +224,22 @@ Token Lexer::next()
consume(); consume();
} }
token_type = TokenType::NumericLiteral; token_type = TokenType::NumericLiteral;
} else if (m_current_char == '"') { } else if (m_current_char == '"' || m_current_char == '\'') {
char stop_char = m_current_char;
consume(); consume();
while (m_current_char != '"' && !is_eof()) { while (m_current_char != stop_char && m_current_char != '\n' && !is_eof()) {
if (m_current_char == '\\') {
consume(); consume();
} }
consume(); consume();
}
if (m_current_char != stop_char) {
syntax_error("unterminated string literal");
token_type = TokenType::UnterminatedStringLiteral;
} else {
consume();
token_type = TokenType::StringLiteral; token_type = TokenType::StringLiteral;
}
} else if (m_current_char == EOF) { } else if (m_current_char == EOF) {
token_type = TokenType::Eof; token_type = TokenType::Eof;
} else { } else {

View file

@ -38,6 +38,7 @@ class Lexer {
public: public:
explicit Lexer(StringView source); explicit Lexer(StringView source);
Token next(); Token next();
bool has_errors() const { return m_has_errors; }
private: private:
void consume(); void consume();
@ -48,10 +49,13 @@ private:
bool is_block_comment_start() const; bool is_block_comment_start() const;
bool is_block_comment_end() const; bool is_block_comment_end() const;
void syntax_error(const char*);
StringView m_source; StringView m_source;
size_t m_position = 0; size_t m_position = 0;
Token m_current_token; Token m_current_token;
int m_current_char; int m_current_char;
bool m_has_errors = false;
static HashMap<String, TokenType> s_keywords; static HashMap<String, TokenType> s_keywords;
static HashMap<String, TokenType> s_three_char_tokens; static HashMap<String, TokenType> s_three_char_tokens;

View file

@ -186,6 +186,8 @@ const char* Token::name(TokenType type)
return "UnsignedShiftRight"; return "UnsignedShiftRight";
case TokenType::UnsignedShiftRightEquals: case TokenType::UnsignedShiftRightEquals:
return "UnsignedShiftRightEquals"; return "UnsignedShiftRightEquals";
case TokenType::UnterminatedStringLiteral:
return "UnterminatedStringLiteral";
case TokenType::Var: case TokenType::Var:
return "Var"; return "Var";
case TokenType::Void: case TokenType::Void:

View file

@ -109,6 +109,7 @@ enum class TokenType {
Typeof, Typeof,
UnsignedShiftRight, UnsignedShiftRight,
UnsignedShiftRightEquals, UnsignedShiftRightEquals,
UnterminatedStringLiteral,
Var, Var,
Void, Void,
While, While,