diff options
author | Carter Anderson <mcanders1@gmail.com> | 2018-11-04 16:51:59 -0800 |
---|---|---|
committer | Carter Anderson <mcanders1@gmail.com> | 2018-11-24 18:29:23 -0800 |
commit | d339824f154074454a783a4a2a517199df2d7c35 (patch) | |
tree | 33aeb3690163519ae04c32ccfc4d93cd0e29b686 /modules/mono/editor/script_class_parser.cpp | |
parent | 958786166218462b4dea46847cbbeb6de339360b (diff) |
Parse C# generics and type constraints correctly
Diffstat (limited to 'modules/mono/editor/script_class_parser.cpp')
-rw-r--r-- | modules/mono/editor/script_class_parser.cpp | 101 |
1 files changed, 97 insertions, 4 deletions
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp index bc8eed81cf..9042bff74a 100644 --- a/modules/mono/editor/script_class_parser.cpp +++ b/modules/mono/editor/script_class_parser.cpp @@ -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; |