summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Base/home/anon/js/strings.js7
-rw-r--r--Libraries/LibJS/Lexer.cpp23
-rw-r--r--Libraries/LibJS/Lexer.h4
-rw-r--r--Libraries/LibJS/Token.cpp2
-rw-r--r--Libraries/LibJS/Token.h1
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,