2022-07-14 14:12:25 -07:00
|
|
|
extends Object
|
|
|
|
|
2022-07-23 23:56:37 -07:00
|
|
|
class_name RDP_Parser
|
|
|
|
|
2022-07-14 14:12:25 -07:00
|
|
|
const NodeType = \
|
|
|
|
{
|
|
|
|
program = "Program",
|
|
|
|
|
|
|
|
expr_Assignment = "Assignment Expression",
|
|
|
|
expr_Call = "Call Expression",
|
|
|
|
expr_ClassExtend = "Class Extension",
|
|
|
|
expr_Binary = "Binary Expression",
|
|
|
|
expr_Logical = "Logical Expression",
|
|
|
|
expr_Member = "Member Expression",
|
|
|
|
expr_New = "New Expression",
|
|
|
|
expr_Super = "Super Expression",
|
|
|
|
expr_This = "This Expression",
|
|
|
|
expr_Unary = "Unary Expression",
|
|
|
|
|
|
|
|
def_Class = "Class Declaration",
|
|
|
|
def_Procedure = "Function Declaration",
|
|
|
|
def_Variable = "Variable Declaration",
|
|
|
|
|
|
|
|
literal_Bool = "Boolean Literal",
|
|
|
|
literal_Numeric = "Numeric Literal",
|
|
|
|
literal_String = "String Literal",
|
|
|
|
literal_Null = "Null Literal",
|
|
|
|
|
|
|
|
stmt_Block = "Block Statement",
|
|
|
|
stmt_Conditional = "Conditional Statement",
|
|
|
|
stmt_Expression = "Expression Statement",
|
|
|
|
stmt_Empty = "Empty Statement",
|
|
|
|
stmt_Variable = "Variable Statement",
|
|
|
|
stmt_While = "While Statement",
|
|
|
|
stmt_DoWhile = "Do-While Statement",
|
|
|
|
stmt_For = "For Statement",
|
|
|
|
stmt_Return = "Return Statement",
|
|
|
|
|
|
|
|
sym_Identifier = "Identifier"
|
|
|
|
}
|
|
|
|
|
|
|
|
class PNode:
|
|
|
|
var Type : String
|
|
|
|
var Value # Not specifing a type implicity declares a Variant type.
|
|
|
|
|
|
|
|
func array_Serialize(array, fn_objSerializer) :
|
|
|
|
var result = []
|
|
|
|
|
|
|
|
for entry in array :
|
|
|
|
if typeof(entry) == TYPE_ARRAY :
|
|
|
|
result.append( array_Serialize( entry, fn_objSerializer ))
|
|
|
|
|
|
|
|
elif typeof(entry) == TYPE_OBJECT :
|
|
|
|
fn_objSerializer.set_instance(entry)
|
|
|
|
result.append( fn_objSerializer.call_func() )
|
|
|
|
|
|
|
|
else :
|
|
|
|
result.append( entry )
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
func to_SExpression():
|
|
|
|
var expression = [ Type ]
|
|
|
|
|
|
|
|
if typeof(Value) == TYPE_ARRAY :
|
|
|
|
var \
|
|
|
|
to_SExpression_Fn = FuncRef.new()
|
|
|
|
to_SExpression_Fn.set_function("to_SExpression")
|
|
|
|
|
|
|
|
var array = array_Serialize( self.Value, to_SExpression_Fn )
|
|
|
|
|
|
|
|
expression.append(array)
|
|
|
|
return expression
|
|
|
|
|
|
|
|
if typeof(Value) == TYPE_OBJECT :
|
|
|
|
var result = [ Type, Value.to_SExpression() ]
|
|
|
|
return result
|
|
|
|
|
|
|
|
expression.append(Value)
|
|
|
|
return expression
|
|
|
|
|
|
|
|
func to_Dictionary():
|
|
|
|
if typeof(Value) == TYPE_ARRAY :
|
|
|
|
var \
|
|
|
|
to_Dictionary_Fn = FuncRef.new()
|
|
|
|
to_Dictionary_Fn.set_function("to_Dictionary")
|
|
|
|
|
|
|
|
var array = array_Serialize( self.Value, to_Dictionary_Fn )
|
|
|
|
var result = \
|
|
|
|
{
|
|
|
|
Type = self.Type,
|
|
|
|
Value = array
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
|
|
|
|
if typeof(Value) == TYPE_OBJECT :
|
|
|
|
var result = \
|
|
|
|
{
|
|
|
|
Type = self.Type,
|
|
|
|
Value = self.Value.to_Dictionary()
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
|
|
|
|
var result = \
|
|
|
|
{
|
|
|
|
Type = self.Type,
|
|
|
|
Value = self.Value
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-23 23:56:37 -07:00
|
|
|
var SLexer : Script = preload("res://RDP/Scripts/RDP_Lexer.gd")
|
2022-07-14 14:12:25 -07:00
|
|
|
var TokenType = SLexer.TokenType
|
2022-07-23 23:56:37 -07:00
|
|
|
var NextToken : RDP_Lexer.Token
|
2022-07-14 14:12:25 -07:00
|
|
|
var Lexer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------- HELPERS
|
|
|
|
|
|
|
|
# Gets the next token only if the current token is the specified intended token (tokenType)
|
|
|
|
func eat(tokenType):
|
|
|
|
var currToken = NextToken
|
|
|
|
|
|
|
|
assert(currToken != null, "eat: NextToken was null")
|
|
|
|
|
|
|
|
var assertStrTmplt = "eat: Unexpected token: {value}, expected: {type}"
|
|
|
|
var assertStr = assertStrTmplt.format({"value" : currToken.Value, "type" : tokenType})
|
|
|
|
|
|
|
|
assert(currToken.Type == tokenType, assertStr)
|
|
|
|
|
|
|
|
NextToken = Lexer.next_Token()
|
|
|
|
|
|
|
|
return currToken
|
|
|
|
|
|
|
|
func is_Literal():
|
|
|
|
return \
|
|
|
|
NextToken.Type == TokenType.literal_Number \
|
|
|
|
|| NextToken.Type == TokenType.literal_String \
|
|
|
|
|| NextToken.Type == TokenType.literal_BTrue \
|
|
|
|
|| NextToken.Type == TokenType.literal_BFalse \
|
|
|
|
|| NextToken.Type == TokenType.literal_Null
|
|
|
|
|
|
|
|
# BinaryExpression
|
|
|
|
# : MultiplicativeExpression
|
|
|
|
# | AdditiveExpression
|
|
|
|
# ;
|
|
|
|
func parse_BinaryExpression(parse_fn, operatorToken):
|
|
|
|
var left = parse_fn.call_func()
|
|
|
|
|
|
|
|
while NextToken.Type == operatorToken:
|
|
|
|
var operator = eat(operatorToken)
|
|
|
|
var right = parse_fn.call_func()
|
|
|
|
|
|
|
|
var \
|
|
|
|
nestedNode = PNode.new()
|
|
|
|
nestedNode.Type = NodeType.expr_Binary
|
|
|
|
nestedNode.Value = []
|
|
|
|
nestedNode.Value.append(operator.Value)
|
|
|
|
nestedNode.Value.append(left)
|
|
|
|
nestedNode.Value.append(right)
|
|
|
|
|
|
|
|
left = nestedNode;
|
|
|
|
|
|
|
|
return left
|
|
|
|
|
|
|
|
# LogicalExpression
|
|
|
|
# : LogicalAndExpression
|
|
|
|
# | LogicalOrExpression
|
|
|
|
# ;
|
|
|
|
func parse_LogicalExpression(parse_fn, operatorToken):
|
|
|
|
var left = parse_fn.call_func()
|
|
|
|
|
|
|
|
while NextToken.Type == operatorToken :
|
|
|
|
var operator = eat(operatorToken).Value
|
|
|
|
var right = parse_fn.call_func()
|
|
|
|
|
|
|
|
var \
|
|
|
|
nestedNode = PNode.new()
|
|
|
|
nestedNode.Type = NodeType.expr_Logical
|
|
|
|
nestedNode.Value = []
|
|
|
|
nestedNode.Value.append(operator)
|
|
|
|
nestedNode.Value.append(left)
|
|
|
|
nestedNode.Value.append(right)
|
|
|
|
|
|
|
|
left = nestedNode
|
|
|
|
|
|
|
|
return left
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------ END HELPERS
|
|
|
|
|
|
|
|
# Parses the text program description into an AST.
|
|
|
|
func parse(lexer):
|
|
|
|
Lexer = lexer
|
|
|
|
NextToken = lexer.next_Token()
|
|
|
|
|
|
|
|
return parse_Program()
|
|
|
|
|
|
|
|
# > parse
|
|
|
|
# Program
|
|
|
|
# : StatementList
|
|
|
|
# : Literal
|
|
|
|
# ;
|
|
|
|
func parse_Program():
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.program
|
|
|
|
node.Value = parse_StatementList(null)
|
|
|
|
|
|
|
|
if node.Value == [ null ] :
|
|
|
|
print("WTF")
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Program
|
|
|
|
# > BlockStatement
|
|
|
|
# StatementList
|
|
|
|
# : Statement
|
|
|
|
# | StatementList Statement -> Statement ...
|
|
|
|
# ;
|
|
|
|
func parse_StatementList(endToken):
|
|
|
|
var statementList = [ parse_Statement() ]
|
|
|
|
|
|
|
|
while NextToken != null && NextToken.Type != endToken :
|
|
|
|
statementList.append( parse_Statement() )
|
|
|
|
|
|
|
|
return statementList
|
|
|
|
|
|
|
|
# > StatementList
|
|
|
|
# > If_Statement
|
|
|
|
# > WhileStatement
|
|
|
|
# Statement
|
|
|
|
# : ExpressionStatement
|
|
|
|
# | BlockStatement
|
|
|
|
# | EmptyStatement
|
|
|
|
# | VariableStatement
|
|
|
|
# | If_Statement
|
|
|
|
# | IterationStatement
|
|
|
|
# | FunctionDeclaration
|
|
|
|
# | ReturnStatement
|
|
|
|
# | ClassDeclaration
|
|
|
|
# ;
|
|
|
|
func parse_Statement():
|
|
|
|
if NextToken == null :
|
|
|
|
return null
|
|
|
|
|
|
|
|
match NextToken.Type :
|
|
|
|
TokenType.def_If :
|
|
|
|
return parse_If_Statement()
|
|
|
|
TokenType.def_End :
|
|
|
|
return parse_EmptyStatement()
|
|
|
|
TokenType.def_BStart :
|
|
|
|
return parse_BlockStatement()
|
|
|
|
TokenType.def_Var :
|
|
|
|
return parse_VariableStatement()
|
|
|
|
TokenType.def_While :
|
|
|
|
return parse_IterationStatement()
|
|
|
|
TokenType.def_Do :
|
|
|
|
return parse_IterationStatement()
|
|
|
|
TokenType.def_For :
|
|
|
|
return parse_IterationStatement()
|
|
|
|
TokenType.def_Proc:
|
|
|
|
return parse_FunctionDeclaration()
|
|
|
|
TokenType.def_Return:
|
|
|
|
return parse_ReturnStatement()
|
|
|
|
TokenType.def_Class:
|
|
|
|
return parse_ClassDeclaration()
|
|
|
|
|
|
|
|
return parse_ExpressionStatement()
|
|
|
|
|
|
|
|
# If Statement
|
|
|
|
# : if ( Expression ) Statement
|
|
|
|
# | if ( Expression ) Statement else Statement
|
|
|
|
# ;
|
|
|
|
func parse_If_Statement():
|
|
|
|
eat(TokenType.def_If)
|
|
|
|
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
var condition = parse_Expression()
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
var consequent = parse_Statement()
|
|
|
|
var alternative = null
|
|
|
|
|
|
|
|
if NextToken != null && NextToken.Type == TokenType.def_Else :
|
|
|
|
eat(TokenType.def_Else)
|
|
|
|
alternative = parse_Statement()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Conditional
|
|
|
|
node.Value = [ condition, consequent, alternative ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# EmptyStatement
|
|
|
|
# ;
|
|
|
|
func parse_EmptyStatement():
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Empty
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# BlockStatement
|
|
|
|
# : { OptStatementList }
|
|
|
|
# ;
|
|
|
|
func parse_BlockStatement():
|
|
|
|
eat(TokenType.def_BStart)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Block
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.def_BEnd :
|
|
|
|
node.Value = parse_StatementList(TokenType.def_BEnd)
|
|
|
|
else :
|
|
|
|
node.Value = []
|
|
|
|
|
|
|
|
eat(TokenType.def_BEnd)
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# VariableStatement
|
|
|
|
# : VariableStatementInit StatementEnd
|
|
|
|
# ;
|
|
|
|
func parse_VariableStatement():
|
|
|
|
var varStatement = parse_VariableStatementInit()
|
|
|
|
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
return varStatement
|
|
|
|
|
|
|
|
# > VariableStatement
|
|
|
|
# VariableStatementInit
|
|
|
|
# : VarDeclare VariableDeclarationList
|
|
|
|
# ;
|
|
|
|
func parse_VariableStatementInit():
|
|
|
|
eat(TokenType.def_Var)
|
|
|
|
|
|
|
|
var declarations = parse_VariableDeclarationList()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Variable
|
|
|
|
node.Value = declarations
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# IterationStatement
|
|
|
|
# : WhileStatement
|
|
|
|
# | DoWhileStatement
|
|
|
|
# | ForStatement
|
|
|
|
# ;
|
|
|
|
func parse_IterationStatement():
|
|
|
|
match NextToken.Type:
|
|
|
|
TokenType.def_While :
|
|
|
|
return parse_WhileStatement()
|
|
|
|
TokenType.def_Do :
|
|
|
|
return parse_DoWhileStatement()
|
|
|
|
TokenType.def_For :
|
|
|
|
return parse_ForStatement()
|
|
|
|
|
|
|
|
# > IterationStatement
|
|
|
|
# WhileStatement
|
|
|
|
# : while ( Expression ) Statement
|
|
|
|
# ;
|
|
|
|
func parse_WhileStatement():
|
|
|
|
eat(TokenType.def_While)
|
|
|
|
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
var condition = parse_Expression()
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
var body = parse_Statement()
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_While
|
|
|
|
node.Value = [ condition, body ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > IterationStatement
|
|
|
|
# DoWhileStatement
|
|
|
|
# : do Statement while ( Expression )
|
|
|
|
# ;
|
|
|
|
func parse_DoWhileStatement():
|
|
|
|
eat(TokenType.def_Do)
|
|
|
|
|
|
|
|
var body = parse_Statement()
|
|
|
|
|
|
|
|
eat(TokenType.def_While)
|
|
|
|
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
var condition = parse_Expression()
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_DoWhile
|
|
|
|
node.Value = [ condition, body ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > IterationStatement
|
|
|
|
# ForStatement
|
|
|
|
# : for (
|
|
|
|
# OptForStatementInit ;
|
|
|
|
# OptExpression ;
|
|
|
|
# OptExpression
|
|
|
|
# )
|
|
|
|
# Statement
|
|
|
|
# ;
|
|
|
|
func parse_ForStatement():
|
|
|
|
eat(TokenType.def_For)
|
|
|
|
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
|
|
|
|
var init = null
|
|
|
|
var condition = null
|
|
|
|
var update = null
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.def_End :
|
|
|
|
init = parse_ForStatementInit()
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.def_End :
|
|
|
|
condition = parse_Expression()
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.expr_PEnd :
|
|
|
|
update = parse_Expression()
|
|
|
|
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
var body = parse_Statement()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_For
|
|
|
|
node.Value = [ init, condition, update, body ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > ForStatement
|
|
|
|
# ForStatementInit
|
|
|
|
# : VariableStatemetnInit
|
|
|
|
# | Expression
|
|
|
|
# ;
|
|
|
|
func parse_ForStatementInit():
|
|
|
|
if NextToken.Type == TokenType.def_Var :
|
|
|
|
return parse_VariableStatementInit()
|
|
|
|
|
|
|
|
return parse_Expression()
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# FunctionDeclaration
|
|
|
|
# : FuncDeclare ( OptFomralParameterList ) BlockStatement
|
|
|
|
# ;
|
|
|
|
func parse_FunctionDeclaration():
|
|
|
|
|
|
|
|
eat(TokenType.def_Proc)
|
|
|
|
|
|
|
|
var name = parse_Identifier()
|
|
|
|
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
|
|
|
|
var params
|
|
|
|
if NextToken.Type != TokenType.expr_PEnd :
|
|
|
|
params = parse_FormalParameterList()
|
|
|
|
else :
|
|
|
|
params = []
|
|
|
|
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
var body = parse_BlockStatement()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.def_Procedure
|
|
|
|
node.Value = [ name, params, body ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > FunctionDeclaration
|
|
|
|
# FormalParameterList
|
|
|
|
# : Identifier
|
|
|
|
# | FormalParameterList , Identifier
|
|
|
|
# ;
|
|
|
|
func parse_FormalParameterList():
|
|
|
|
var params = [ parse_Identifier() ]
|
|
|
|
|
|
|
|
while NextToken.Type == TokenType.delim_Comma :
|
|
|
|
eat(TokenType.delim_Comma)
|
|
|
|
params.append(parse_Identifier())
|
|
|
|
|
|
|
|
return params
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# ReturnStatement
|
|
|
|
# : return OptExpression
|
|
|
|
# ;
|
|
|
|
func parse_ReturnStatement():
|
|
|
|
eat(TokenType.def_Return)
|
|
|
|
|
|
|
|
var argument = null
|
|
|
|
if NextToken.Type != TokenType.def_End :
|
|
|
|
argument = parse_Expression()
|
|
|
|
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Return
|
|
|
|
node.Value = argument
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# ClassDeclaration
|
|
|
|
# : class Identifier OptClassExtends BLockStatement
|
|
|
|
# ;
|
|
|
|
func parse_ClassDeclaration():
|
|
|
|
eat(TokenType.def_Class)
|
|
|
|
|
|
|
|
var identifier = parse_Identifier()
|
|
|
|
var superClass = null
|
|
|
|
|
|
|
|
if NextToken.Type == TokenType.expr_Extends :
|
|
|
|
superClass = parse_ClassExtension()
|
|
|
|
|
|
|
|
var body = parse_BlockStatement()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.def_Class
|
|
|
|
node.Value = [ identifier, superClass, body ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > ClassDeclaration
|
|
|
|
# ClassExtension
|
|
|
|
# : extends Identifier
|
|
|
|
# ;
|
|
|
|
func parse_ClassExtension():
|
|
|
|
eat(TokenType.expr_Extends)
|
|
|
|
|
|
|
|
return parse_Identifier()
|
|
|
|
|
|
|
|
# > Statement
|
|
|
|
# ExpressionStatement
|
|
|
|
# : Expression
|
|
|
|
# ;
|
|
|
|
func parse_ExpressionStatement():
|
|
|
|
var expression = parse_Expression()
|
|
|
|
eat(TokenType.def_End)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.stmt_Expression
|
|
|
|
node.Value = expression
|
|
|
|
|
|
|
|
return expression
|
|
|
|
|
|
|
|
# > ExpressionStatement
|
|
|
|
# > If_Statement
|
|
|
|
# > WhileStatement
|
|
|
|
# > PrimaryExpression
|
|
|
|
# Expression
|
|
|
|
# : AssignmentExpression
|
|
|
|
# ;
|
|
|
|
func parse_Expression():
|
|
|
|
return parse_AssignmentExpression()
|
|
|
|
|
|
|
|
# > VariableStatement
|
|
|
|
# VariableDeclarationList
|
|
|
|
# : VariableDeclaration
|
|
|
|
# | VariableDelcarationList , VariableDeclaration -> VariableDelcaration , ...
|
|
|
|
func parse_VariableDeclarationList():
|
|
|
|
var \
|
|
|
|
declarations = []
|
|
|
|
declarations.append(parse_VariableDeclaration())
|
|
|
|
|
|
|
|
while NextToken.Type == TokenType.delim_Comma :
|
|
|
|
eat(TokenType.delim_Comma)
|
|
|
|
declarations.append(parse_VariableDeclaration())
|
|
|
|
|
|
|
|
return declarations
|
|
|
|
|
|
|
|
# > VariableDeclarationList
|
|
|
|
# VariableDeclaration
|
|
|
|
# : Identifier OptVariableInitalizer
|
|
|
|
# ;
|
|
|
|
func parse_VariableDeclaration():
|
|
|
|
var identifier = parse_Identifier()
|
|
|
|
var initalizer
|
|
|
|
if NextToken.Type != TokenType.def_End \
|
|
|
|
&& NextToken.Type != TokenType.delim_Comma :
|
|
|
|
initalizer = parse_VariableInitializer()
|
|
|
|
else :
|
|
|
|
initalizer = null
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.def_Variable
|
|
|
|
node.Value = [ identifier, initalizer ]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > VariableDeclaration
|
|
|
|
# VariableInitializer
|
|
|
|
# : Assignment AssignmentExpression
|
|
|
|
# ;
|
|
|
|
func parse_VariableInitializer():
|
|
|
|
eat(TokenType.op_Assign)
|
|
|
|
|
|
|
|
return parse_AssignmentExpression()
|
|
|
|
|
|
|
|
# > Expression
|
|
|
|
# > VariableInitializer
|
|
|
|
# > AssignmentExpression
|
|
|
|
# AssignmentExpression
|
|
|
|
# : RelationalExpression
|
|
|
|
# | ResolvedSymbol AssignmentOperator AssignmetnExpression
|
|
|
|
# ;
|
|
|
|
func parse_AssignmentExpression():
|
|
|
|
var left = parse_LogicalOrExpression()
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.op_Assign \
|
|
|
|
&& NextToken.Type != TokenType.op_CAssign :
|
|
|
|
return left
|
|
|
|
|
|
|
|
var assignmentOp;
|
|
|
|
|
|
|
|
if NextToken.Type == TokenType.op_Assign :
|
|
|
|
assignmentOp = eat(TokenType.op_Assign)
|
|
|
|
elif NextToken.Type == TokenType.op_CAssign :
|
|
|
|
assignmentOp = eat(TokenType.op_CAssign)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_Assignment
|
|
|
|
node.Value = \
|
|
|
|
[
|
|
|
|
assignmentOp.Value,
|
|
|
|
left,
|
|
|
|
parse_AssignmentExpression()
|
|
|
|
]
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > VariableDeclaration
|
|
|
|
# > ParenthesizedExpression
|
|
|
|
# Identifier
|
|
|
|
# : IdentifierSymbol
|
|
|
|
# ;
|
|
|
|
func parse_Identifier():
|
|
|
|
var name = eat(TokenType.sym_Identifier).Value
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.sym_Identifier
|
|
|
|
node.Value = name
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > AssignmentExpression
|
|
|
|
# Logical Or Expression
|
|
|
|
# : LogicalAndExpression Logical_Or LogicalOrExpression
|
|
|
|
# | LogicalOrExpression
|
|
|
|
# ;
|
|
|
|
func parse_LogicalOrExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("pasre_LogicalAndExpression")
|
|
|
|
|
|
|
|
return parse_LogicalExpression(parseFn, TokenType.op_LOr)
|
|
|
|
|
|
|
|
# > LogicaOrExpression
|
|
|
|
# Logical And Expression
|
|
|
|
# : EqualityExpression Logical_And LogicalAndExpression
|
|
|
|
# | EqualityExpression
|
|
|
|
# ;
|
|
|
|
func pasre_LogicalAndExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("parse_EqualityExpression")
|
|
|
|
|
|
|
|
return parse_LogicalExpression(parseFn, TokenType.op_LAnd)
|
|
|
|
|
|
|
|
# Equality Operators: ==, !=
|
|
|
|
#
|
|
|
|
# > LogicalAndExpression
|
|
|
|
# EqualityExpression
|
|
|
|
# : RelationalExpression EqualityOp RelationalExpression
|
|
|
|
# | RelationalExpression
|
|
|
|
# ;
|
|
|
|
func parse_EqualityExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("parse_RelationalExpression")
|
|
|
|
|
|
|
|
return parse_BinaryExpression(parseFn, TokenType.op_Equality)
|
|
|
|
|
|
|
|
# Relational Operators: >, >=, <, <=
|
|
|
|
#
|
|
|
|
# > EqualityExpression
|
|
|
|
# Relational Expression
|
|
|
|
# : AdditiveExpression
|
|
|
|
# | AdditiveExpression RelationalOp RelationalExpression
|
|
|
|
# ;
|
|
|
|
func parse_RelationalExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("parse_AdditiveExpression")
|
|
|
|
|
|
|
|
return parse_BinaryExpression(parseFn, TokenType.op_Relational)
|
|
|
|
|
|
|
|
# > RelationalExpression
|
|
|
|
# AdditiveExpression
|
|
|
|
# : MultiplicativeExpression
|
|
|
|
# | AdditiveExpression AdditiveOp MultiplicativeExpression -> MultiplicativeExpression AdditiveOp ... Literal
|
|
|
|
# ;
|
|
|
|
func parse_AdditiveExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("parse_MultiplicativeExpression")
|
|
|
|
|
|
|
|
return parse_BinaryExpression(parseFn, TokenType.op_Additive)
|
|
|
|
|
|
|
|
# > AdditiveExpression
|
|
|
|
# MultiplicativeExpression
|
|
|
|
# : UnaryExpressioon
|
|
|
|
# : MultiplicativeExpression MultiplicativeOp UnaryExpression -> UnaryExpression MultiplicativeOp ... Literal
|
|
|
|
# ;
|
|
|
|
func parse_MultiplicativeExpression():
|
|
|
|
var \
|
|
|
|
parseFn = FuncRef.new()
|
|
|
|
parseFn.set_instance(self)
|
|
|
|
parseFn.set_function("parse_UnaryExpression")
|
|
|
|
|
|
|
|
return parse_BinaryExpression(parseFn, TokenType.op_Multiplicative)
|
|
|
|
|
|
|
|
# > MultiplicativeExpression
|
|
|
|
# > UnaryExpression
|
|
|
|
# UnaryExpression
|
|
|
|
# : ResolvedSymbol
|
|
|
|
# | AdditiveOp UnaryExpression
|
|
|
|
# | Logical_Not UnaryExpression
|
|
|
|
# ;
|
|
|
|
func parse_UnaryExpression():
|
|
|
|
var operator
|
|
|
|
match NextToken.Type:
|
|
|
|
TokenType.op_Additive:
|
|
|
|
operator = eat(TokenType.op_Additive).Value
|
|
|
|
TokenType.op_LNot:
|
|
|
|
operator = eat(TokenType.op_LNot).Value
|
|
|
|
|
|
|
|
if operator == null :
|
|
|
|
return parse_ResolvedSymbol()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_Unary
|
|
|
|
node.Value = [ operator, parse_UnaryExpression() ]
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
|
|
|
# > UnaryExpression
|
|
|
|
# > PrimaryExpression
|
|
|
|
# ResolvedSymbol (LeftHandExpression)
|
|
|
|
# : MemberExpression
|
|
|
|
# ;
|
|
|
|
func parse_ResolvedSymbol():
|
|
|
|
return parse_FunctionExpression()
|
|
|
|
|
|
|
|
# > ResolvedSymbol
|
|
|
|
# FunctionExpression
|
|
|
|
# : Super
|
|
|
|
# | MemberExpression
|
|
|
|
# | CallExpression
|
|
|
|
# ;
|
|
|
|
func parse_FunctionExpression():
|
|
|
|
if NextToken.Type == TokenType.expr_Super :
|
|
|
|
return parse_CallExpression(parse_SuperExpression())
|
|
|
|
|
|
|
|
var member = parse_MemberExpression()
|
|
|
|
|
|
|
|
if NextToken.Type == TokenType.expr_PStart :
|
|
|
|
return parse_CallExpression(member)
|
|
|
|
|
|
|
|
return member
|
|
|
|
|
|
|
|
# > FunctionExpression
|
|
|
|
# Super
|
|
|
|
# : super
|
|
|
|
# ;
|
|
|
|
func parse_SuperExpression():
|
|
|
|
eat(TokenType.expr_Super)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_Super
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > ResolvedSymbol
|
|
|
|
# MemberExpression
|
|
|
|
# : PrimaryExpression
|
|
|
|
# | MemberExpression . Identifier
|
|
|
|
# | MemberExpression [ Expression ]
|
|
|
|
# ;
|
|
|
|
func parse_MemberExpression():
|
|
|
|
var expression = parse_PrimaryExpression()
|
|
|
|
|
|
|
|
while NextToken.Type == TokenType.delim_SMR || NextToken.Type == TokenType.expr_SBStart :
|
|
|
|
if NextToken.Type == TokenType.delim_SMR :
|
|
|
|
eat(TokenType.delim_SMR)
|
|
|
|
|
|
|
|
var member = parse_Identifier()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_Member
|
|
|
|
node.Value = [ false, expression, member ]
|
|
|
|
|
|
|
|
expression = node
|
|
|
|
|
|
|
|
if NextToken.Type == TokenType.expr_SBStart :
|
|
|
|
eat(TokenType.expr_SBStart)
|
|
|
|
|
|
|
|
var sbExpression = parse_Expression()
|
|
|
|
|
|
|
|
eat(TokenType.expr_SBEnd)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_Member
|
|
|
|
node.Value = [ true, expression, sbExpression ]
|
|
|
|
|
|
|
|
expression = node
|
|
|
|
|
|
|
|
return expression
|
|
|
|
|
|
|
|
# > FunctionExpression
|
|
|
|
# CallExpression
|
|
|
|
# : Callee Arguments
|
|
|
|
# ;
|
|
|
|
#
|
|
|
|
# Callee
|
|
|
|
# : MemberExpression
|
|
|
|
# | CallExpression
|
|
|
|
# ;
|
|
|
|
func parse_CallExpression(callee):
|
|
|
|
var \
|
|
|
|
callExpression = PNode.new()
|
|
|
|
callExpression.Type = NodeType.expr_Call
|
|
|
|
callExpression.Value = \
|
|
|
|
[
|
|
|
|
callee,
|
|
|
|
parse_Arguments()
|
|
|
|
]
|
|
|
|
|
|
|
|
if NextToken.Type == TokenType.expr_PStart :
|
|
|
|
callExpression = parse_CallExpression(callExpression)
|
|
|
|
|
|
|
|
return callExpression
|
|
|
|
|
|
|
|
# > CallExpression
|
|
|
|
# Arugments
|
|
|
|
# : ( OptArgumentList )
|
|
|
|
# ;
|
|
|
|
func parse_Arguments():
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
|
|
|
|
var argumentList = null
|
|
|
|
|
|
|
|
if NextToken.Type != TokenType.expr_PEnd :
|
|
|
|
argumentList = parse_ArgumentList()
|
|
|
|
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
return argumentList
|
|
|
|
|
|
|
|
# > Arguments
|
|
|
|
# ArgumentList
|
|
|
|
# : AssignmentExpression
|
|
|
|
# | ArgumentList , AssignmentExpression
|
|
|
|
# ;
|
|
|
|
func parse_ArgumentList():
|
|
|
|
var argumentList = [ parse_AssignmentExpression() ]
|
|
|
|
|
|
|
|
while NextToken.Type == TokenType.delim_Comma :
|
|
|
|
eat(TokenType.delim_Comma)
|
|
|
|
|
|
|
|
argumentList.append( parse_AssignmentExpression() )
|
|
|
|
|
|
|
|
return argumentList
|
|
|
|
|
|
|
|
|
|
|
|
# > MemberExpression
|
|
|
|
# PrimaryExpression
|
|
|
|
# : Literal
|
|
|
|
# | ParenthesizedExpression
|
|
|
|
# | Identifier
|
|
|
|
# | ThisExpression
|
|
|
|
# | NewExpression
|
|
|
|
# ;
|
|
|
|
func parse_PrimaryExpression():
|
|
|
|
if is_Literal():
|
|
|
|
return parse_Literal()
|
|
|
|
|
|
|
|
match NextToken.Type:
|
|
|
|
TokenType.expr_PStart:
|
|
|
|
return parse_ParenthesizedExpression()
|
|
|
|
|
|
|
|
TokenType.sym_Identifier:
|
|
|
|
var identifier = parse_Identifier()
|
|
|
|
|
|
|
|
if identifier.Type == NodeType.sym_Identifier :
|
|
|
|
return identifier
|
|
|
|
|
|
|
|
var assertStrTmplt = "parse_PrimaryExpression: (Identifier) Unexpected symbol: {value}"
|
|
|
|
var assertStr = assertStrTmplt.format({"value" : identifier.Type})
|
|
|
|
assert(true != true, assertStr)
|
|
|
|
|
|
|
|
TokenType.sym_This :
|
|
|
|
return parse_ThisExpression()
|
|
|
|
|
|
|
|
TokenType.expr_New :
|
|
|
|
return parse_NewExpression()
|
|
|
|
|
|
|
|
return parse_ResolvedSymbol()
|
|
|
|
|
|
|
|
# > PrimaryExpression
|
|
|
|
# Literal
|
|
|
|
# : NumericLiteral
|
|
|
|
# | StringLiteral
|
|
|
|
# | BooleanLiteral
|
|
|
|
# | NullLiteral
|
|
|
|
# ;
|
|
|
|
func parse_Literal():
|
|
|
|
match NextToken.Type :
|
|
|
|
TokenType.literal_Number:
|
|
|
|
return parse_NumericLiteral()
|
|
|
|
TokenType.literal_String:
|
|
|
|
return parse_StringLiteral()
|
|
|
|
TokenType.literal_BTrue:
|
|
|
|
return parse_BooleanLiteral(TokenType.literal_BTrue)
|
|
|
|
TokenType.literal_BFalse:
|
|
|
|
return parse_BooleanLiteral(TokenType.literal_BFalse)
|
|
|
|
TokenType.literal_Null:
|
|
|
|
return parse_NullLiteral()
|
|
|
|
|
|
|
|
assert(false, "parse_Literal: Was not able to detect valid literal type from NextToken")
|
|
|
|
|
|
|
|
# > PrimaryExpression
|
|
|
|
# ParenthesizedExpression
|
|
|
|
# : ( Expression )
|
|
|
|
# ;
|
|
|
|
func parse_ParenthesizedExpression():
|
|
|
|
eat(TokenType.expr_PStart)
|
|
|
|
|
|
|
|
var expression = parse_Expression()
|
|
|
|
|
|
|
|
eat(TokenType.expr_PEnd)
|
|
|
|
|
|
|
|
return expression
|
|
|
|
|
|
|
|
# > PrimaryExpression
|
|
|
|
# ThisExpression
|
|
|
|
# : this
|
|
|
|
# ;
|
|
|
|
func parse_ThisExpression():
|
|
|
|
eat(TokenType.sym_This)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_This
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > PrimaryExpression
|
|
|
|
# NewExpression
|
|
|
|
# : new MemberExpression Arugments -> new MyNamespace.MyClass(1, 2);
|
|
|
|
# ;
|
|
|
|
func parse_NewExpression():
|
|
|
|
eat(TokenType.expr_New)
|
|
|
|
|
|
|
|
var memberExp = parse_MemberExpression()
|
|
|
|
var args = parse_Arguments()
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.expr_New
|
|
|
|
node.Value = [ memberExp, args ]
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
|
|
|
# > Literal
|
|
|
|
# NumericLiteral
|
|
|
|
# : Number
|
|
|
|
# ;
|
|
|
|
func parse_NumericLiteral():
|
|
|
|
var Token = eat(TokenType.literal_Number)
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.literal_Numeric
|
|
|
|
node.Value = int( Token.Value )
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Literal
|
|
|
|
# StringLiteral
|
|
|
|
# : String
|
|
|
|
# ;
|
|
|
|
func parse_StringLiteral():
|
|
|
|
var Token = eat(TokenType.literal_String)
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.literal_String
|
|
|
|
node.Value = Token.Value.substr( 1, Token.Value.length() - 2 )
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Literal
|
|
|
|
# BooleanLiteral
|
|
|
|
# : true
|
|
|
|
# | false
|
|
|
|
# ;
|
|
|
|
func parse_BooleanLiteral(token):
|
|
|
|
eat(token)
|
|
|
|
var value
|
|
|
|
if (TokenType.literal_BTrue == token) :
|
|
|
|
value = true
|
|
|
|
elif (TokenType.literal_BFalse == token) :
|
|
|
|
value = false
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.literal_Bool
|
|
|
|
node.Value = value
|
|
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
# > Literal
|
|
|
|
# NullLiteral
|
|
|
|
# : null
|
|
|
|
# ;
|
|
|
|
func parse_NullLiteral():
|
|
|
|
eat(TokenType.literal_Null)
|
|
|
|
|
|
|
|
var \
|
|
|
|
node = PNode.new()
|
|
|
|
node.Type = NodeType.literal_Null
|
|
|
|
node.Value = null
|
|
|
|
|
|
|
|
return node
|
|
|
|
|