Parse C# generics and type constraints correctly

This commit is contained in:
Carter Anderson 2018-11-04 16:51:59 -08:00
parent 9587861662
commit d339824f15
3 changed files with 100 additions and 4 deletions

View file

@ -0,0 +1,2 @@
# nuget packages
packages

View file

@ -259,6 +259,8 @@ Error ScriptClassParser::_skip_generic_type_params() {
if (err)
return err;
continue;
} else if (tk == TK_OP_GREATER) {
return OK;
} else if (tk != TK_COMMA) {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
@ -312,27 +314,108 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
Token tk = get_token();
bool generic = false;
if (tk == TK_OP_LESS) {
// We don't add it to the base list if it's generic
Error err = _skip_generic_type_params();
if (err)
return err;
} else if (tk == TK_COMMA) {
// We don't add it to the base list if it's generic
generic = true;
tk = get_token();
}
if (tk == TK_COMMA) {
Error err = _parse_class_base(r_base);
if (err)
return err;
r_base.push_back(name);
} else if (tk == TK_IDENTIFIER && String(value) == "where") {
Error err = _parse_type_constraints();
if (err) {
return err;
}
// An open curly bracket was parsed by _parse_type_constraints, so we can exit
} else if (tk == TK_CURLY_BRACKET_OPEN) {
r_base.push_back(name);
// we are finished when we hit the open curly bracket
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
if (!generic) {
r_base.push_back(name);
}
return OK;
}
Error ScriptClassParser::_parse_type_constraints() {
Token tk = get_token();
if (tk != TK_IDENTIFIER) {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
tk = get_token();
if (tk != TK_COLON) {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
while (true) {
tk = get_token();
if (tk == TK_IDENTIFIER) {
if (String(value) == "where") {
return _parse_type_constraints();
}
tk = get_token();
if (tk == TK_PERIOD) {
while (true) {
tk = get_token();
if (tk != TK_IDENTIFIER) {
error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
tk = get_token();
if (tk != TK_PERIOD)
break;
}
}
}
if (tk == TK_COMMA) {
continue;
} else if (tk == TK_IDENTIFIER && String(value) == "where") {
return _parse_type_constraints();
} else if (tk == TK_SYMBOL && String(value) == "(") {
tk = get_token();
if (tk != TK_SYMBOL || String(value) != ")") {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
} else if (tk == TK_OP_LESS) {
Error err = _skip_generic_type_params();
if (err)
return err;
} else if (tk == TK_CURLY_BRACKET_OPEN) {
return OK;
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
}
}
Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
Token tk = get_token();
@ -425,6 +508,16 @@ Error ScriptClassParser::parse(const String &p_code) {
Error err = _skip_generic_type_params();
if (err)
return err;
} else if (tk == TK_IDENTIFIER && String(value) == "where") {
Error err = _parse_type_constraints();
if (err) {
return err;
}
// An open curly bracket was parsed by _parse_type_constraints, so we can exit
curly_stack++;
type_curly_stack++;
break;
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;

View file

@ -65,6 +65,7 @@ private:
Error _parse_type_full_name(String &r_full_name);
Error _parse_class_base(Vector<String> &r_base);
Error _parse_type_constraints();
Error _parse_namespace_name(String &r_name, int &r_curly_stack);
public: