Ver código fonte

LibJS: Add TokenType::TemplateLiteral

This is required for template literals - we're not quite there yet, but at
least the parser can now tell us when this token is encountered -
currently this yields "Unexpected token Invalid". Not really helpful.

The character is a "backtick", but as we already have
TokenType::{StringLiteral,RegexLiteral} this seemed like a fitting name.

This also enables syntax highlighting for template literals in the js
REPL and LibGUI's JSSyntaxHighlighter.
Linus Groh 5 anos atrás
pai
commit
95b51e857d

+ 1 - 0
Libraries/LibGUI/JSSyntaxHighlighter.cpp

@@ -42,6 +42,7 @@ static TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenType type)
     case JS::TokenType::NumericLiteral:
         return { palette.syntax_number() };
     case JS::TokenType::StringLiteral:
+    case JS::TokenType::TemplateLiteral:
     case JS::TokenType::RegexLiteral:
     case JS::TokenType::UnterminatedStringLiteral:
         return { palette.syntax_string() };

+ 5 - 2
Libraries/LibJS/Lexer.cpp

@@ -337,7 +337,7 @@ Token Lexer::next()
             }
         }
         token_type = TokenType::NumericLiteral;
-    } else if (m_current_char == '"' || m_current_char == '\'') {
+    } else if (m_current_char == '"' || m_current_char == '\'' || m_current_char == '`') {
         char stop_char = m_current_char;
         consume();
         while (m_current_char != stop_char && m_current_char != '\n' && !is_eof()) {
@@ -351,7 +351,10 @@ Token Lexer::next()
             token_type = TokenType::UnterminatedStringLiteral;
         } else {
             consume();
-            token_type = TokenType::StringLiteral;
+            if (stop_char == '`')
+                token_type = TokenType::TemplateLiteral;
+            else
+                token_type = TokenType::StringLiteral;
         }
     } else if (m_current_char == EOF) {
         token_type = TokenType::Eof;

+ 1 - 0
Libraries/LibJS/Parser.cpp

@@ -1037,6 +1037,7 @@ bool Parser::match_expression() const
     return type == TokenType::BoolLiteral
         || type == TokenType::NumericLiteral
         || type == TokenType::StringLiteral
+        || type == TokenType::TemplateLiteral
         || type == TokenType::NullLiteral
         || type == TokenType::Identifier
         || type == TokenType::New

+ 4 - 1
Libraries/LibJS/Token.cpp

@@ -74,7 +74,7 @@ double Token::double_value() const
 
 String Token::string_value() const
 {
-    ASSERT(type() == TokenType::StringLiteral);
+    ASSERT(type() == TokenType::StringLiteral || type() == TokenType::TemplateLiteral);
     StringBuilder builder;
     for (size_t i = 1; i < m_value.length() - 1; ++i) {
         if (m_value[i] == '\\' && i + 1 < m_value.length() - 1) {
@@ -107,6 +107,9 @@ String Token::string_value() const
             case '"':
                 builder.append('"');
                 break;
+            case '`':
+                builder.append('`');
+                break;
             case '\\':
                 builder.append('\\');
                 break;

+ 1 - 0
Libraries/LibJS/Token.h

@@ -111,6 +111,7 @@ namespace JS {
     __ENUMERATE_JS_TOKEN(SlashEquals)                 \
     __ENUMERATE_JS_TOKEN(StringLiteral)               \
     __ENUMERATE_JS_TOKEN(Switch)                      \
+    __ENUMERATE_JS_TOKEN(TemplateLiteral)             \
     __ENUMERATE_JS_TOKEN(This)                        \
     __ENUMERATE_JS_TOKEN(Throw)                       \
     __ENUMERATE_JS_TOKEN(Tilde)                       \

+ 1 - 0
Userland/js.cpp

@@ -453,6 +453,7 @@ int main(int argc, char** argv)
                     stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
                     break;
                 case JS::TokenType::StringLiteral:
+                case JS::TokenType::TemplateLiteral:
                 case JS::TokenType::RegexLiteral:
                 case JS::TokenType::UnterminatedStringLiteral:
                     stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Green), Line::Style::Bold });