summaryrefslogtreecommitdiff
path: root/modules/gdscript/gd_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gd_parser.cpp')
-rw-r--r--modules/gdscript/gd_parser.cpp127
1 files changed, 73 insertions, 54 deletions
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 1540bb51f8..9023fd4bf4 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -6,6 +6,7 @@
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -184,8 +185,8 @@ void GDParser::_make_completable_call(int p_arg) {
bool GDParser::_get_completable_identifier(CompletionType p_type, StringName &identifier) {
identifier = StringName();
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
- identifier = tokenizer->get_token_identifier();
+ if (tokenizer->is_token_literal()) {
+ identifier = tokenizer->get_token_literal();
tokenizer->advance();
}
if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
@@ -200,8 +201,8 @@ bool GDParser::_get_completable_identifier(CompletionType p_type, StringName &id
completion_ident_is_call = false;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
- identifier = identifier.operator String() + tokenizer->get_token_identifier().operator String();
+ if (tokenizer->is_token_literal()) {
+ identifier = identifier.operator String() + tokenizer->get_token_literal().operator String();
tokenizer->advance();
}
@@ -295,17 +296,6 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
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) {
@@ -319,7 +309,15 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
} break;
default: {
- done = true;
+ // Instead of checking for TK_IDENTIFIER, we check with is_token_literal, as this allows us to use match/sync/etc. as a name
+ if (need_identifier && tokenizer->is_token_literal()) {
+ path += String(tokenizer->get_token_literal());
+ tokenizer->advance();
+ need_identifier = false;
+ } else {
+ done = true;
+ }
+
break;
}
}
@@ -388,6 +386,19 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
tokenizer->advance();
+ if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ completion_cursor = StringName();
+ completion_node = p_parent;
+ completion_type = COMPLETION_RESOURCE_PATH;
+ completion_class = current_class;
+ completion_function = current_function;
+ completion_line = tokenizer->get_token_line();
+ completion_block = current_block;
+ completion_argument = 0;
+ completion_found = true;
+ tokenizer->advance();
+ }
+
String path;
bool found_constant = false;
bool valid = false;
@@ -459,10 +470,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
_set_error("Expected ')' after 'preload' path");
return NULL;
}
+ tokenizer->advance();
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = res;
- tokenizer->advance();
expr = constant;
} else if (tokenizer->get_token() == GDTokenizer::TK_PR_YIELD) {
@@ -571,7 +582,8 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
cn->value = Variant::get_numeric_constant_value(bi_type, identifier);
expr = cn;
- } else if (tokenizer->get_token(1) == GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE || tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER || tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_FUNC)) {
+ } else if (tokenizer->get_token(1) == GDTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) {
+ // We check with is_token_literal, as this allows us to use match/sync/etc. as a name
//function or constructor
OperatorNode *op = alloc_node<OperatorNode>();
@@ -613,7 +625,8 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = op;
- } else if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
+ } else if (tokenizer->is_token_literal(0, true)) {
+ // We check with is_token_literal, as this allows us to use match/sync/etc. as a name
//identifier (reference)
const ClassNode *cln = current_class;
@@ -813,10 +826,11 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
if (expecting == DICT_EXPECT_KEY) {
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1) == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->is_token_literal() && tokenizer->get_token(1) == GDTokenizer::TK_OP_ASSIGN) {
+ // We check with is_token_literal, as this allows us to use match/sync/etc. as a name
//lua style identifier, easier to write
ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value = tokenizer->get_token_identifier();
+ cn->value = tokenizer->get_token_literal();
key = cn;
tokenizer->advance(2);
expecting = DICT_EXPECT_VALUE;
@@ -856,7 +870,8 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = dict;
- } else if (tokenizer->get_token() == GDTokenizer::TK_PERIOD && (tokenizer->get_token(1) == GDTokenizer::TK_IDENTIFIER || tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) && tokenizer->get_token(2) == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ } else if (tokenizer->get_token() == GDTokenizer::TK_PERIOD && (tokenizer->is_token_literal(1) || tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) && tokenizer->get_token(2) == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ // We check with is_token_literal, as this allows us to use match/sync/etc. as a name
// parent call
tokenizer->advance(); //goto identifier
@@ -908,7 +923,8 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
//indexing using "."
- if (tokenizer->get_token(1) != GDTokenizer::TK_CURSOR && tokenizer->get_token(1) != GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1) != GDTokenizer::TK_BUILT_IN_FUNC) {
+ if (tokenizer->get_token(1) != GDTokenizer::TK_CURSOR && !tokenizer->is_token_literal(1)) {
+ // We check with is_token_literal, as this allows us to use match/sync/etc. as a name
_set_error("Expected identifier as member");
return NULL;
} else if (tokenizer->get_token(2) == GDTokenizer::TK_PARENTHESIS_OPEN) {
@@ -1063,7 +1079,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
case GDTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break;
case GDTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break;
case GDTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break;
- case GDTokenizer::TK_PR_EXTENDS: op = OperatorNode::OP_EXTENDS; break;
+ case GDTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break;
case GDTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break;
case GDTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break;
default: valid = false; break;
@@ -1103,7 +1119,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
switch (expression[i].op) {
- case OperatorNode::OP_EXTENDS:
+ case OperatorNode::OP_IS:
priority = -1;
break; //before anything
@@ -1406,7 +1422,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
}
}
- if (op->op == OperatorNode::OP_EXTENDS) {
+ if (op->op == OperatorNode::OP_IS) {
//nothing much
return op;
}
@@ -2264,6 +2280,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
if (!is_first_line && tab_level.back()->prev() && tab_level.back()->prev()->get() == indent_level) {
// pythonic single-line expression, don't parse future lines
tab_level.pop_back();
+ p_block->end_line = tokenizer->get_token_line();
return;
}
is_first_line = false;
@@ -2326,12 +2343,12 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
//variale declaration and (eventual) initialization
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("Expected identifier for local variable name.");
return;
}
- StringName n = tokenizer->get_token_identifier();
+ StringName n = tokenizer->get_token_literal();
tokenizer->advance();
if (current_function) {
for (int i = 0; i < current_function->arguments.size(); i++) {
@@ -2352,8 +2369,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
check_block = check_block->parent_block;
}
- p_block->variables.push_back(n); //line?
- p_block->variable_lines.push_back(tokenizer->get_token_line());
+ int var_line = tokenizer->get_token_line();
//must know when the local variable is declared
LocalVarNode *lv = alloc_node<LocalVarNode>();
@@ -2383,6 +2399,10 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
c->value = Variant();
assigned = c;
}
+ //must be added later, to avoid self-referencing.
+ p_block->variables.push_back(n); //line?
+ p_block->variable_lines.push_back(var_line);
+
IdentifierNode *id = alloc_node<IdentifierNode>();
id->name = n;
@@ -2420,7 +2440,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_if->body);
if (!_enter_indent_block(cf_if->body)) {
- _set_error("Expected intended block after 'if'");
+ _set_error("Expected indented block after 'if'");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -2435,9 +2455,8 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
while (true) {
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
- tokenizer->advance();
- }
+ while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE && _parse_newline())
+ ;
if (tab_level.back()->get() < indent_level) { //not at current indent level
p_block->end_line = tokenizer->get_token_line();
@@ -2557,7 +2576,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("identifier expected after 'for'");
}
@@ -2612,7 +2631,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
ConstantNode *cn = alloc_node<ConstantNode>();
switch (args.size()) {
- case 1: cn->value = constants[0]; break;
+ case 1: cn->value = (int)constants[0]; break;
case 2: cn->value = Vector2(constants[0], constants[1]); break;
case 3: cn->value = Vector3(constants[0], constants[1], constants[2]); break;
}
@@ -2625,7 +2644,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
on->arguments.push_back(tn);
switch (args.size()) {
- case 1: tn->vtype = Variant::REAL; break;
+ case 1: tn->vtype = Variant::INT; break;
case 2: tn->vtype = Variant::VECTOR2; break;
case 3: tn->vtype = Variant::VECTOR3; break;
}
@@ -3094,7 +3113,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance(); //var before the identifier is allowed
}
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("Expected identifier for argument.");
return;
@@ -3246,7 +3265,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
case GDTokenizer::TK_PR_SIGNAL: {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal()) {
_set_error("Expected identifier after 'signal'.");
return;
}
@@ -3268,7 +3287,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
break;
}
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("Expected identifier in signal argument.");
return;
}
@@ -3833,13 +3852,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
bool onready = tokenizer->get_token(-1) == GDTokenizer::TK_PR_ONREADY;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("Expected identifier for member variable name.");
return;
}
- member.identifier = tokenizer->get_token_identifier();
+ member.identifier = tokenizer->get_token_literal();
member.expression = NULL;
member._export.name = member.identifier;
member.line = tokenizer->get_token_line();
@@ -3965,11 +3984,11 @@ void GDParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
//just comma means using only getter
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
- _set_error("Expected identifier for setter function after 'notify'.");
+ if (!tokenizer->is_token_literal()) {
+ _set_error("Expected identifier for setter function after 'setget'.");
}
- member.setter = tokenizer->get_token_identifier();
+ member.setter = tokenizer->get_token_literal();
tokenizer->advance();
}
@@ -3978,11 +3997,11 @@ void GDParser::_parse_class(ClassNode *p_class) {
//there is a getter
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal()) {
_set_error("Expected identifier for getter function after ','.");
}
- member.getter = tokenizer->get_token_identifier();
+ member.getter = tokenizer->get_token_literal();
tokenizer->advance();
}
}
@@ -4000,13 +4019,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
ClassNode::Constant constant;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (!tokenizer->is_token_literal(0, true)) {
_set_error("Expected name (identifier) for constant.");
return;
}
- constant.identifier = tokenizer->get_token_identifier();
+ constant.identifier = tokenizer->get_token_literal();
tokenizer->advance();
if (tokenizer->get_token() != GDTokenizer::TK_OP_ASSIGN) {
@@ -4047,8 +4066,8 @@ void GDParser::_parse_class(ClassNode *p_class) {
Dictionary enum_dict;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
- enum_name = tokenizer->get_token_identifier();
+ if (tokenizer->is_token_literal(0, true)) {
+ enum_name = tokenizer->get_token_literal();
tokenizer->advance();
}
if (tokenizer->get_token() != GDTokenizer::TK_CURLY_BRACKET_OPEN) {
@@ -4065,7 +4084,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
break; // End of enum
- } else if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ } else if (!tokenizer->is_token_literal(0, true)) {
if (tokenizer->get_token() == GDTokenizer::TK_EOF) {
_set_error("Unexpected end of file.");
@@ -4074,10 +4093,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
return;
- } else { // tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER
+ } else { // tokenizer->is_token_literal(0, true)
ClassNode::Constant constant;
- constant.identifier = tokenizer->get_token_identifier();
+ constant.identifier = tokenizer->get_token_literal();
tokenizer->advance();