diff options
Diffstat (limited to 'modules/gdscript/gd_parser.cpp')
-rw-r--r-- | modules/gdscript/gd_parser.cpp | 131 |
1 files changed, 122 insertions, 9 deletions
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 09c47770a2..aab6946364 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -265,6 +265,98 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ tokenizer->advance(); expr=subexpr; + } else if (tokenizer->get_token()==GDTokenizer::TK_DOLLAR) { + tokenizer->advance(); + + String path; + + bool need_identifier=true; + bool done=false; + + while(!done) { + + switch(tokenizer->get_token()) { + case GDTokenizer::TK_CURSOR: { + completion_cursor=StringName(); + completion_type=COMPLETION_GET_NODE; + completion_class=current_class; + completion_function=current_function; + completion_line=tokenizer->get_token_line(); + completion_cursor=path; + completion_argument=0; + completion_block=current_block; + completion_found=true; + tokenizer->advance(); + } break; + case GDTokenizer::TK_CONSTANT: { + + if (!need_identifier) { + done=true; + break; + } + + if (tokenizer->get_token_constant().get_type()!=Variant::STRING) { + _set_error("Expected string constant or identifier after '$' or '/'."); + return NULL; + } + + path+=String(tokenizer->get_token_constant()); + tokenizer->advance(); + need_identifier=false; + + } break; + case GDTokenizer::TK_IDENTIFIER: { + if (!need_identifier) { + done=true; + break; + } + + path+=String(tokenizer->get_token_identifier()); + tokenizer->advance(); + need_identifier=false; + + } break; + case GDTokenizer::TK_OP_DIV: { + + if (need_identifier) { + done=true; + break; + } + + path+="/"; + tokenizer->advance(); + need_identifier=true; + + } break; + default: { + done=true; + break; + } + } + } + + if (path=="") { + _set_error("Path expected after $."); + return NULL; + + } + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=OperatorNode::OP_CALL; + + op->arguments.push_back(alloc_node<SelfNode>()); + + IdentifierNode *funcname = alloc_node<IdentifierNode>(); + funcname->name="get_node"; + + op->arguments.push_back(funcname); + + ConstantNode *nodepath = alloc_node<ConstantNode>(); + nodepath->value = NodePath(StringName(path)); + op->arguments.push_back(nodepath); + + expr=op; + } else if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { tokenizer->advance(); continue; //no point in cursor in the middle of expression @@ -540,14 +632,15 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ expr = id; } - } else if (/*tokenizer->get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer->get_token()==GDTokenizer::TK_OP_SUB || tokenizer->get_token()==GDTokenizer::TK_OP_NOT || tokenizer->get_token()==GDTokenizer::TK_OP_BIT_INVERT) { + } else if (tokenizer->get_token()==GDTokenizer::TK_OP_ADD || tokenizer->get_token()==GDTokenizer::TK_OP_SUB || tokenizer->get_token()==GDTokenizer::TK_OP_NOT || tokenizer->get_token()==GDTokenizer::TK_OP_BIT_INVERT) { - //single prefix operators like !expr -expr ++expr --expr + //single prefix operators like !expr +expr -expr ++expr --expr alloc_node<OperatorNode>(); Expression e; e.is_op=true; switch(tokenizer->get_token()) { + case GDTokenizer::TK_OP_ADD: e.op=OperatorNode::OP_POS; break; case GDTokenizer::TK_OP_SUB: e.op=OperatorNode::OP_NEG; break; case GDTokenizer::TK_OP_NOT: e.op=OperatorNode::OP_NOT; break; case GDTokenizer::TK_OP_BIT_INVERT: e.op=OperatorNode::OP_BIT_INVERT;; break; @@ -995,6 +1088,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ case OperatorNode::OP_BIT_INVERT: priority=0; unary=true; break; case OperatorNode::OP_NEG: priority=1; unary=true; break; + case OperatorNode::OP_POS: priority=1; unary=true; break; case OperatorNode::OP_MUL: priority=2; break; case OperatorNode::OP_DIV: priority=2; break; @@ -1223,7 +1317,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { //reduce constant array expression ConstantNode *cn = alloc_node<ConstantNode>(); - Array arr(!p_to_const); + Array arr; //print_line("mk array "+itos(!p_to_const)); arr.resize(an->elements.size()); for(int i=0;i<an->elements.size();i++) { @@ -1258,7 +1352,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { //reduce constant array expression ConstantNode *cn = alloc_node<ConstantNode>(); - Dictionary dict(!p_to_const); + Dictionary dict; for(int i=0;i<dn->elements.size();i++) { ConstantNode *key_c = static_cast<ConstantNode*>(dn->elements[i].key); ConstantNode *value_c = static_cast<ConstantNode*>(dn->elements[i].value); @@ -1476,6 +1570,15 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { return op; } + if (op->arguments[0]->type==Node::TYPE_OPERATOR) { + OperatorNode *on = static_cast<OperatorNode*>(op->arguments[0]); + if (on->op != OperatorNode::OP_INDEX && on->op != OperatorNode::OP_INDEX_NAMED) { + _set_error("Can't assign to an expression",tokenizer->get_token_line()-1); + error_line=op->line; + return op; + } + } + } break; default: { break; } } @@ -1512,6 +1615,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { //unary operators case OperatorNode::OP_NEG: { _REDUCE_UNARY(Variant::OP_NEGATE); } break; + case OperatorNode::OP_POS: { _REDUCE_UNARY(Variant::OP_POSITIVE); } break; case OperatorNode::OP_NOT: { _REDUCE_UNARY(Variant::OP_NOT); } break; case OperatorNode::OP_BIT_INVERT: { _REDUCE_UNARY(Variant::OP_BIT_NEGATE); } break; //binary operators (in precedence order) @@ -2588,7 +2692,7 @@ void GDParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="FLAGS") { - current_export.hint=PROPERTY_HINT_ALL_FLAGS; + //current_export.hint=PROPERTY_HINT_ALL_FLAGS; tokenizer->advance(); if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { @@ -2950,7 +3054,7 @@ void GDParser::_parse_class(ClassNode *p_class) { } else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { String identifier = tokenizer->get_token_identifier(); - if (!ObjectTypeDB::is_type(identifier,"Resource")) { + if (!ClassDB::is_parent_class(identifier,"Resource")) { current_export=PropertyInfo(); _set_error("Export hint not a type or resource."); @@ -3168,7 +3272,7 @@ void GDParser::_parse_class(ClassNode *p_class) { return; } member._export.hint=PROPERTY_HINT_RESOURCE_TYPE; - member._export.hint_string=res->get_type(); + member._export.hint_string=res->get_class(); } } } @@ -3406,7 +3510,16 @@ void GDParser::_parse_class(ClassNode *p_class) { } break; - + + case GDTokenizer::TK_CONSTANT: { + if(tokenizer->get_token_constant().get_type() == Variant::STRING) { + tokenizer->advance(); + // Ignore + } else { + _set_error(String()+"Unexpected constant of type: "+Variant::get_type_name(tokenizer->get_token_constant().get_type())); + return; + } + } break; default: { |