diff options
Diffstat (limited to 'modules/gdscript')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 89 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 114 | ||||
-rw-r--r-- | modules/gdscript/gdscript_tokenizer.cpp | 11 | ||||
-rw-r--r-- | modules/gdscript/gdscript_tokenizer.h | 3 |
6 files changed, 147 insertions, 76 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index b3ebd4fe4b..f221aac5fe 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1735,7 +1735,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "NAN", "self", "true", + "void", // functions + "as", "assert", "breakpoint", "class", diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 70f3d704ae..69a0575efe 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -430,6 +430,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: return dst_addr; } break; + case GDScriptParser::Node::TYPE_CAST: { + const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression); + return _parse_expression(codegen, cn->source_node, p_stack_level); + } break; case GDScriptParser::Node::TYPE_OPERATOR: { //hell breaks loose diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d62112d3f1..37781cb934 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1087,6 +1087,27 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s break; } + /*****************/ + /* Parse Casting */ + /*****************/ + + bool has_casting = expr->type == Node::TYPE_CAST; + if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_AS) { + if (has_casting) { + _set_error("Unexpected 'as'."); + return NULL; + } + CastNode *cn = alloc_node<CastNode>(); + DataType casttype; + if (!_parse_type(casttype)) { + _set_error("Expected type after 'as'."); + return NULL; + } + has_casting = true; + cn->source_node = expr; + expr = cn; + } + /******************/ /* Parse Operator */ /******************/ @@ -1110,7 +1131,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s //assign, if allowed is only allowed on the first operator #define _VALIDATE_ASSIGN \ - if (!p_allow_assign) { \ + if (!p_allow_assign || has_casting) { \ _set_error("Unexpected assign."); \ return NULL; \ } \ @@ -2488,6 +2509,14 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { Node *assigned = NULL; + if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { + DataType vartype; + if (!_parse_type(vartype)) { + _set_error("Expected type for variable."); + return; + } + } + if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { tokenizer->advance(); @@ -3150,7 +3179,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { //class inside class :D StringName name; - StringName extends; if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) { @@ -3279,6 +3307,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); + if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { + DataType argtype; + if (!_parse_type(argtype)) { + _set_error("Expected type for argument."); + return; + } + } + if (defaulting && tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) { _set_error("Default parameter expected."); @@ -3386,6 +3422,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } + if (tokenizer->get_token() == GDScriptTokenizer::TK_FORWARD_ARROW) { + DataType rettype; + if (!_parse_type(rettype, true)) { + _set_error("Expected return type for function."); + return; + } + } + if (!_enter_indent_block(block)) { _set_error("Indented block expected."); @@ -4113,6 +4157,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; + if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { + DataType vartype; + if (!_parse_type(vartype)) { + _set_error("Expected type for class variable."); + return; + } + } + if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { #ifdef DEBUG_ENABLED @@ -4272,6 +4324,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { constant.identifier = tokenizer->get_token_literal(); tokenizer->advance(); + if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { + DataType consttype; + if (!_parse_type(consttype)) { + _set_error("Expected type for class constant."); + return; + } + } + if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) { _set_error("Constant expects assignment."); return; @@ -4423,6 +4483,31 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } +bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) { + tokenizer->advance(); + + r_type.has_type = true; + + switch (tokenizer->get_token()) { + case GDScriptTokenizer::TK_IDENTIFIER: { + StringName id = tokenizer->get_token_identifier(); + } break; + case GDScriptTokenizer::TK_BUILT_IN_TYPE: { + } break; + case GDScriptTokenizer::TK_PR_VOID: { + if (!p_can_be_void) { + return false; + } + } break; + default: { + return false; + } + } + + tokenizer->advance(); + return true; +} + void GDScriptParser::_set_error(const String &p_error, int p_line, int p_column) { if (error_set) diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index b88a59537c..a71bd96ded 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -39,6 +39,39 @@ class GDScriptParser { public: + struct ClassNode; + + struct DataType { + enum { + BUILTIN, + NATIVE, + SCRIPT, + GDSCRIPT, + CLASS + } kind; + + bool has_type; + + Variant::Type builtin_type; + StringName native_type; + Ref<Script> script_type; + ClassNode *class_type; + + DataType *meta_type; + + DataType() : + has_type(false), + meta_type(NULL), + builtin_type(Variant::NIL), + class_type(NULL) {} + + ~DataType() { + if (meta_type) { + memdelete(meta_type); + } + } + }; + struct Node { enum Type { @@ -55,6 +88,7 @@ public: TYPE_OPERATOR, TYPE_CONTROL_FLOW, TYPE_LOCAL_VAR, + TYPE_CAST, TYPE_ASSERT, TYPE_BREAKPOINT, TYPE_NEWLINE, @@ -65,6 +99,9 @@ public: int column; Type type; + virtual DataType get_datatype() const { return DataType(); } + virtual void set_datatype(DataType p_datatype) {} + virtual ~Node() {} }; @@ -340,6 +377,11 @@ public: } }; + struct CastNode : public Node { + Node *source_node; + CastNode() { type = TYPE_CAST; } + }; + struct AssertNode : public Node { Node *condition; AssertNode() { type = TYPE_ASSERT; } @@ -362,76 +404,6 @@ public: }; }; - /* - struct OperatorNode : public Node { - - DataType return_cache; - Operator op; - Vector<Node*> arguments; - virtual DataType get_datatype() const { return return_cache; } - - OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; } - }; - - struct VariableNode : public Node { - - DataType datatype_cache; - StringName name; - virtual DataType get_datatype() const { return datatype_cache; } - - VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; } - }; - - struct ConstantNode : public Node { - - DataType datatype; - Variant value; - virtual DataType get_datatype() const { return datatype; } - - ConstantNode() { type=TYPE_CONSTANT; } - }; - - struct BlockNode : public Node { - - Map<StringName,DataType> variables; - List<Node*> statements; - BlockNode() { type=TYPE_BLOCK; } - }; - - struct ControlFlowNode : public Node { - - FlowOperation flow_op; - Vector<Node*> statements; - ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;} - }; - - struct MemberNode : public Node { - - DataType datatype; - StringName name; - Node* owner; - virtual DataType get_datatype() const { return datatype; } - MemberNode() { type=TYPE_MEMBER; } - }; - - - struct ProgramNode : public Node { - - struct Function { - StringName name; - FunctionNode*function; - }; - - Map<StringName,DataType> builtin_variables; - Map<StringName,DataType> preexisting_variables; - - Vector<Function> functions; - BlockNode *body; - - ProgramNode() { type=TYPE_PROGRAM; } - }; -*/ - enum CompletionType { COMPLETION_NONE, COMPLETION_BUILT_IN_TYPE_CONSTANT, @@ -515,6 +487,8 @@ private: void _parse_class(ClassNode *p_class); bool _end_statement(); + bool _parse_type(DataType &r_type, bool p_can_be_void = false); + Error _parse(const String &p_base_path); public: diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 1d30871e3f..940bdcbc8d 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -101,6 +101,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "setget", "const", "var", + "as", + "void", "enum", "preload", "assert", @@ -125,6 +127,7 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "'.'", "'?'", "':'", + "'->'", "'$'", "'\\n'", "PI", @@ -197,6 +200,8 @@ static const _kws _keyword_list[] = { { GDScriptTokenizer::TK_PR_EXPORT, "export" }, { GDScriptTokenizer::TK_PR_SETGET, "setget" }, { GDScriptTokenizer::TK_PR_VAR, "var" }, + { GDScriptTokenizer::TK_PR_AS, "as" }, + { GDScriptTokenizer::TK_PR_VOID, "void" }, { GDScriptTokenizer::TK_PR_PRELOAD, "preload" }, { GDScriptTokenizer::TK_PR_ASSERT, "assert" }, { GDScriptTokenizer::TK_PR_YIELD, "yield" }, @@ -707,11 +712,9 @@ void GDScriptTokenizerText::_advance() { if (GETCHAR(1) == '=') { _make_token(TK_OP_ASSIGN_SUB); INCPOS(1); - /* - } else if (GETCHAR(1)=='-') { - _make_token(TK_OP_MINUS_MINUS); + } else if (GETCHAR(1) == '>') { + _make_token(TK_FORWARD_ARROW); INCPOS(1); - */ } else { _make_token(TK_OP_SUB); } diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index c1f611fe73..5bd303224c 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -106,6 +106,8 @@ public: TK_PR_SETGET, TK_PR_CONST, TK_PR_VAR, + TK_PR_AS, + TK_PR_VOID, TK_PR_ENUM, TK_PR_PRELOAD, TK_PR_ASSERT, @@ -131,6 +133,7 @@ public: TK_QUESTION_MARK, TK_COLON, TK_DOLLAR, + TK_FORWARD_ARROW, TK_NEWLINE, TK_CONST_PI, TK_CONST_TAU, |