Sfoglia il codice sorgente

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

Stephan Unverwerth 5 anni fa
parent
commit
c0e6234219

+ 7 - 0
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

+ 19 - 4
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 {

+ 4 - 0
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;

+ 2 - 0
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:

+ 1 - 0
Libraries/LibJS/Token.h

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