mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 08:27:35 +00:00
LibJS: Add Javascript lexer and parser
This adds a basic Javascript lexer and parser. It can parse the currently existing demo programs. More work needs to be done to turn it into a complete parser than can parse arbitrary JS Code. The lexer outputs tokens with preceeding whitespace and comments in the trivia member. This should allow us to generate the exact source code by concatenating the generated tokens. The parser is written in a way that it always returns a complete syntax tree. Error conditions are represented as nodes in the tree. This simplifies the code and allows it to be used as an early stage parser, e.g for parsing JS documents in an IDE while editing the source code.:
This commit is contained in:
parent
17705d23fb
commit
f3a9eba987
11 changed files with 1069 additions and 36 deletions
|
@ -48,7 +48,31 @@ protected:
|
|||
private:
|
||||
};
|
||||
|
||||
class ScopeNode : public ASTNode {
|
||||
class Statement : public ASTNode {
|
||||
};
|
||||
|
||||
class ErrorStatement final : public Statement {
|
||||
public:
|
||||
Value execute(Interpreter&) const { return js_undefined(); }
|
||||
const char* class_name() const override { return "ErrorStatement"; }
|
||||
};
|
||||
|
||||
class ExpressionStatement final : public Statement {
|
||||
public:
|
||||
ExpressionStatement(NonnullOwnPtr<Expression> expression)
|
||||
: m_expression(move(expression))
|
||||
{
|
||||
}
|
||||
|
||||
Value execute(Interpreter&) const override;
|
||||
const char* class_name() const override { return "ExpressionStatement"; }
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
private:
|
||||
NonnullOwnPtr<Expression> m_expression;
|
||||
};
|
||||
|
||||
class ScopeNode : public Statement {
|
||||
public:
|
||||
template<typename T, typename... Args>
|
||||
T& append(Args&&... args)
|
||||
|
@ -57,8 +81,12 @@ public:
|
|||
m_children.append(move(child));
|
||||
return static_cast<T&>(m_children.last());
|
||||
}
|
||||
void append(NonnullOwnPtr<Statement> child)
|
||||
{
|
||||
m_children.append(move(child));
|
||||
}
|
||||
|
||||
const NonnullOwnPtrVector<ASTNode>& children() const { return m_children; }
|
||||
const NonnullOwnPtrVector<Statement>& children() const { return m_children; }
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
|
@ -66,7 +94,7 @@ protected:
|
|||
ScopeNode() {}
|
||||
|
||||
private:
|
||||
NonnullOwnPtrVector<ASTNode> m_children;
|
||||
NonnullOwnPtrVector<Statement> m_children;
|
||||
};
|
||||
|
||||
class Program : public ScopeNode {
|
||||
|
@ -85,7 +113,7 @@ private:
|
|||
virtual const char* class_name() const override { return "BlockStatement"; }
|
||||
};
|
||||
|
||||
class FunctionDeclaration : public ASTNode {
|
||||
class FunctionDeclaration : public Statement {
|
||||
public:
|
||||
FunctionDeclaration(String name, NonnullOwnPtr<ScopeNode> body)
|
||||
: m_name(move(name))
|
||||
|
@ -110,14 +138,20 @@ class Expression : public ASTNode {
|
|||
public:
|
||||
};
|
||||
|
||||
class ReturnStatement : public ASTNode {
|
||||
class ErrorExpression final : public Expression {
|
||||
public:
|
||||
explicit ReturnStatement(NonnullOwnPtr<Expression> argument)
|
||||
Value execute(Interpreter&) const { return js_undefined(); }
|
||||
const char* class_name() const override { return "ErrorExpression"; }
|
||||
};
|
||||
|
||||
class ReturnStatement : public Statement {
|
||||
public:
|
||||
explicit ReturnStatement(OwnPtr<Expression> argument)
|
||||
: m_argument(move(argument))
|
||||
{
|
||||
}
|
||||
|
||||
const Expression& argument() const { return *m_argument; }
|
||||
const Expression* argument() const { return m_argument; }
|
||||
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
|
@ -125,10 +159,10 @@ public:
|
|||
private:
|
||||
virtual const char* class_name() const override { return "ReturnStatement"; }
|
||||
|
||||
NonnullOwnPtr<Expression> m_argument;
|
||||
OwnPtr<Expression> m_argument;
|
||||
};
|
||||
|
||||
class IfStatement : public ASTNode {
|
||||
class IfStatement : public Statement {
|
||||
public:
|
||||
IfStatement(NonnullOwnPtr<Expression> predicate, NonnullOwnPtr<ScopeNode> consequent, NonnullOwnPtr<ScopeNode> alternate)
|
||||
: m_predicate(move(predicate))
|
||||
|
@ -152,7 +186,7 @@ private:
|
|||
NonnullOwnPtr<ScopeNode> m_alternate;
|
||||
};
|
||||
|
||||
class WhileStatement : public ASTNode {
|
||||
class WhileStatement : public Statement {
|
||||
public:
|
||||
WhileStatement(NonnullOwnPtr<Expression> predicate, NonnullOwnPtr<ScopeNode> body)
|
||||
: m_predicate(move(predicate))
|
||||
|
@ -337,7 +371,7 @@ enum class DeclarationType {
|
|||
Let,
|
||||
};
|
||||
|
||||
class VariableDeclaration : public ASTNode {
|
||||
class VariableDeclaration : public Statement {
|
||||
public:
|
||||
VariableDeclaration(NonnullOwnPtr<Identifier> name, OwnPtr<Expression> initializer, DeclarationType declaration_type)
|
||||
: m_declaration_type(declaration_type)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue