diff options
-rw-r--r-- | Base/home/anon/js/strings.js | 7 | ||||
-rw-r--r-- | Libraries/LibJS/Lexer.cpp | 23 | ||||
-rw-r--r-- | Libraries/LibJS/Lexer.h | 4 | ||||
-rw-r--r-- | Libraries/LibJS/Token.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibJS/Token.h | 1 |
5 files changed, 33 insertions, 4 deletions
diff --git a/Base/home/anon/js/strings.js b/Base/home/anon/js/strings.js new file mode 100644 index 0000000000..d707bf090d --- /dev/null +++ b/Base/home/anon/js/strings.js @@ -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 diff --git a/Libraries/LibJS/Lexer.cpp b/Libraries/LibJS/Lexer.cpp index c84810afbe..e783d478cf 100644 --- a/Libraries/LibJS/Lexer.cpp +++ b/Libraries/LibJS/Lexer.cpp @@ -169,6 +169,12 @@ bool Lexer::is_block_comment_end() const 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() { size_t trivia_start = m_position; @@ -218,13 +224,22 @@ Token Lexer::next() consume(); } token_type = TokenType::NumericLiteral; - } else if (m_current_char == '"') { + } else if (m_current_char == '"' || m_current_char == '\'') { + char stop_char = m_current_char; 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(); - token_type = TokenType::StringLiteral; + if (m_current_char != stop_char) { + syntax_error("unterminated string literal"); + token_type = TokenType::UnterminatedStringLiteral; + } else { + consume(); + token_type = TokenType::StringLiteral; + } } else if (m_current_char == EOF) { token_type = TokenType::Eof; } else { diff --git a/Libraries/LibJS/Lexer.h b/Libraries/LibJS/Lexer.h index a91c85ff37..887ef040aa 100644 --- a/Libraries/LibJS/Lexer.h +++ b/Libraries/LibJS/Lexer.h @@ -38,6 +38,7 @@ class Lexer { public: explicit Lexer(StringView source); Token next(); + bool has_errors() const { return m_has_errors; } private: void consume(); @@ -48,10 +49,13 @@ private: bool is_block_comment_start() const; bool is_block_comment_end() const; + void syntax_error(const char*); + StringView m_source; size_t m_position = 0; Token m_current_token; int m_current_char; + bool m_has_errors = false; static HashMap<String, TokenType> s_keywords; static HashMap<String, TokenType> s_three_char_tokens; diff --git a/Libraries/LibJS/Token.cpp b/Libraries/LibJS/Token.cpp index 2698aaffdc..ff379d37db 100644 --- a/Libraries/LibJS/Token.cpp +++ b/Libraries/LibJS/Token.cpp @@ -186,6 +186,8 @@ const char* Token::name(TokenType type) return "UnsignedShiftRight"; case TokenType::UnsignedShiftRightEquals: return "UnsignedShiftRightEquals"; + case TokenType::UnterminatedStringLiteral: + return "UnterminatedStringLiteral"; case TokenType::Var: return "Var"; case TokenType::Void: diff --git a/Libraries/LibJS/Token.h b/Libraries/LibJS/Token.h index 8d442e4a7d..9679c7b902 100644 --- a/Libraries/LibJS/Token.h +++ b/Libraries/LibJS/Token.h @@ -109,6 +109,7 @@ enum class TokenType { Typeof, UnsignedShiftRight, UnsignedShiftRightEquals, + UnterminatedStringLiteral, Var, Void, While, |