diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 342fbc96ac..ad3fc2cf1e 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -349,6 +349,18 @@ void BooleanLiteral::dump(int indent) const printf("BooleanLiteral %s\n", m_value ? "true" : "false"); } +void UndefinedLiteral::dump(int indent) const +{ + print_indent(indent); + printf("undefined\n"); +} + +void NullLiteral::dump(int indent) const +{ + print_indent(indent); + printf("null\n"); +} + void FunctionDeclaration::dump(int indent) const { bool first_time = true; @@ -617,4 +629,14 @@ Value BooleanLiteral::execute(Interpreter&) const return Value(m_value); } +Value UndefinedLiteral::execute(Interpreter&) const +{ + return js_undefined(); +} + +Value NullLiteral::execute(Interpreter&) const +{ + return js_null(); +} + } diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 43a2508769..8578a8530e 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -380,6 +380,34 @@ private: String m_value; }; +class NullLiteral final : public Literal { +public: + explicit NullLiteral() + { + } + + virtual Value execute(Interpreter&) const override; + virtual void dump(int indent) const override; + +private: + virtual const char* class_name() const override { return "NullLiteral"; } + + String m_value; +}; + +class UndefinedLiteral final : public Literal { +public: + explicit UndefinedLiteral() + { + } + + virtual Value execute(Interpreter&) const override; + virtual void dump(int indent) const override; + +private: + virtual const char* class_name() const override { return "UndefinedLiteral"; } +}; + class Identifier final : public Expression { public: explicit Identifier(String string) diff --git a/Libraries/LibJS/Lexer.cpp b/Libraries/LibJS/Lexer.cpp index e783d478cf..3f59ea1867 100644 --- a/Libraries/LibJS/Lexer.cpp +++ b/Libraries/LibJS/Lexer.cpp @@ -60,6 +60,7 @@ Lexer::Lexer(StringView source) s_keywords.set("let", TokenType::Let); s_keywords.set("new", TokenType::New); s_keywords.set("null", TokenType::NullLiteral); + s_keywords.set("undefined", TokenType::UndefinedLiteral); s_keywords.set("return", TokenType::Return); s_keywords.set("true", TokenType::BoolLiteral); s_keywords.set("try", TokenType::Try); diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 9884ec430f..0553e93b80 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -223,6 +223,12 @@ NonnullOwnPtr Parser::parse_primary_expression() return make(consume().bool_value()); case TokenType::StringLiteral: return make(consume().string_value()); + case TokenType::NullLiteral: + consume(); + return make(); + case TokenType::UndefinedLiteral: + consume(); + return make(); case TokenType::CurlyOpen: return parse_object_expression(); default: @@ -498,6 +504,7 @@ bool Parser::match_expression() const return type == TokenType::BoolLiteral || type == TokenType::NumericLiteral || type == TokenType::StringLiteral + || type == TokenType::UndefinedLiteral || type == TokenType::NullLiteral || type == TokenType::Identifier || type == TokenType::New diff --git a/Libraries/LibJS/Token.cpp b/Libraries/LibJS/Token.cpp index da5f75c839..a578122d4d 100644 --- a/Libraries/LibJS/Token.cpp +++ b/Libraries/LibJS/Token.cpp @@ -183,6 +183,8 @@ const char* Token::name(TokenType type) return "Try"; case TokenType::Typeof: return "Typeof"; + case TokenType::UndefinedLiteral: + return "UndefinedLiteral"; case TokenType::UnsignedShiftRight: return "UnsignedShiftRight"; case TokenType::UnsignedShiftRightEquals: diff --git a/Libraries/LibJS/Token.h b/Libraries/LibJS/Token.h index 9679c7b902..fe120d0212 100644 --- a/Libraries/LibJS/Token.h +++ b/Libraries/LibJS/Token.h @@ -107,6 +107,7 @@ enum class TokenType { Tilde, Try, Typeof, + UndefinedLiteral, UnsignedShiftRight, UnsignedShiftRightEquals, UnterminatedStringLiteral,