diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-20 13:18:29 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-20 13:18:29 +0800 |
commit | de16b83e86ac67aa02c188bdcbb3d19088a90b97 (patch) | |
tree | 5376e84a3419203162225a2fe82359a5f3f4060c /src | |
parent | 66fcd19348efb2e16a21124c4465f4b911d87ded (diff) | |
download | mrust-de16b83e86ac67aa02c188bdcbb3d19088a90b97.tar.gz |
Split parse/root.cpp up
Diffstat (limited to 'src')
-rw-r--r-- | src/parse/common.hpp | 1 | ||||
-rw-r--r-- | src/parse/paths.cpp | 180 | ||||
-rw-r--r-- | src/parse/root.cpp | 380 | ||||
-rw-r--r-- | src/parse/types.cpp | 221 |
4 files changed, 425 insertions, 357 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 3ee985c0..3fb5a9ec 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -26,6 +26,7 @@ enum eParsePathGenericMode };
extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
+extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines
extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
extern AST::Path Parse_PathFrom(TokenStream& lex, AST::Path src, eParsePathGenericMode generic_mode);
extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp new file mode 100644 index 00000000..3fb1d779 --- /dev/null +++ b/src/parse/paths.cpp @@ -0,0 +1,180 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * parse/paths.cpp + * - Parsing for module paths + */ +#include "parseerror.hpp" +#include "common.hpp" +#include "../ast/ast.hpp" + +AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); +AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode); +AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode); +::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex); + +AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode) +{ + Token tok; + if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ) + return Parse_Path(lex, true, generic_mode); + else + { + lex.putback(tok); + return Parse_Path(lex, false, generic_mode); + } +} +AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode) +{ + if( is_abs ) + { + Token tok; + if( GET_TOK(tok, lex) == TOK_STRING ) { + ::std::string cratename = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + return Parse_PathFrom(lex, AST::Path(cratename, {}), generic_mode); + } + else { + lex.putback(tok); + return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_mode); + } + } + else + return Parse_PathFrom(lex, AST::Path(), generic_mode); +} + +AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode) +{ + TRACE_FUNCTION_F("path = " << path); + + Token tok; + + tok = lex.getToken(); + while(true) + { + ::std::vector<TypeRef> params; + + CHECK_TOK(tok, TOK_IDENT); + ::std::string component = tok.str(); + + GET_TOK(tok, lex); + if( generic_mode == PATH_GENERIC_TYPE ) + { + if( tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT ) + { + // HACK! Handle breaking << into < < + if( tok.type() == TOK_DOUBLE_LT ) + lex.putback( Token(TOK_LT) ); + + // Type-mode generics "::path::to::Type<A,B>" + params = Parse_Path_GenericList(lex); + tok = lex.getToken(); + } + // HACK - 'Fn*(...) -> ...' notation + else if( tok.type() == TOK_PAREN_OPEN ) + { + DEBUG("Fn() hack"); + ::std::vector<TypeRef> args; + if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) + { + // Empty list + } + else + { + lex.putback(tok); + do { + args.push_back( Parse_Type(lex) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + } + CHECK_TOK(tok, TOK_PAREN_CLOSE); + + TypeRef ret_type = TypeRef( TypeRef::TagUnit() ); + if( GET_TOK(tok, lex) == TOK_THINARROW ) { + ret_type = Parse_Type(lex); + } + else { + lex.putback(tok); + } + DEBUG("- Fn("<<args<<")->"<<ret_type<<""); + + // Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C> + params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), ::std::move(args)) }; + // TODO: Use 'ret_type' as an associated type bound + + GET_TOK(tok, lex); + } + else + { + } + } + if( tok.type() != TOK_DOUBLE_COLON ) { + path.append( AST::PathNode(component, params) ); + break; + } + tok = lex.getToken(); + if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) ) + { + // HACK! Handle breaking << into < < + if( tok.type() == TOK_DOUBLE_LT ) + lex.putback( Token(TOK_LT) ); + + // Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)" + params = Parse_Path_GenericList(lex); + tok = lex.getToken(); + if( tok.type() != TOK_DOUBLE_COLON ) { + path.append( AST::PathNode(component, params) ); + break; + } + GET_TOK(tok, lex); + } + path.append( AST::PathNode(component, params) ); + } + lex.putback(tok); + DEBUG("path = " << path); + return path; +} +/// Parse a list of parameters within a path +::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex) +{ + TRACE_FUNCTION; + Token tok; + + ::std::vector<TypeRef> types; + ::std::vector< ::std::string> lifetimes; + ::std::map< ::std::string, TypeRef> assoc_bounds; + ::std::vector<unsigned int> int_args; + do { + switch(GET_TOK(tok, lex)) + { + case TOK_LIFETIME: + lifetimes.push_back( tok.str() ); + break; + case TOK_IDENT: + if( LOOK_AHEAD(lex) == TOK_EQUAL ) + { + ::std::string name = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_EQUAL); + assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) ); + break; + } + default: + lex.putback(tok); + types.push_back( Parse_Type(lex) ); + break; + } + } while( GET_TOK(tok, lex) == TOK_COMMA ); + + // HACK: Split >> into > + if(tok.type() == TOK_DOUBLE_GT) { + lex.putback(Token(TOK_GT)); + } + else { + CHECK_TOK(tok, TOK_GT); + } + + // TODO: Actually use the lifetimes/assoc_bounds + + return types; +} + diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 7f2ed359..8b8f3b2f 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -10,357 +10,6 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex); AST::MetaItem Parse_MetaItem(TokenStream& lex);
void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*> *prev_modstack, const ::std::string& path);
-AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);
-AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
-AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode);
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
-
-AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
-{
- Token tok;
- if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
- return Parse_Path(lex, true, generic_mode);
- else
- {
- lex.putback(tok);
- return Parse_Path(lex, false, generic_mode);
- }
-}
-AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode)
-{
- if( is_abs )
- {
- Token tok;
- if( GET_TOK(tok, lex) == TOK_STRING ) {
- ::std::string cratename = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- return Parse_PathFrom(lex, AST::Path(cratename, {}), generic_mode);
- }
- else {
- lex.putback(tok);
- return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_mode);
- }
- }
- else
- return Parse_PathFrom(lex, AST::Path(), generic_mode);
-}
-
-AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode)
-{
- TRACE_FUNCTION_F("path = " << path);
-
- Token tok;
-
- tok = lex.getToken();
- while(true)
- {
- ::std::vector<TypeRef> params;
-
- CHECK_TOK(tok, TOK_IDENT);
- ::std::string component = tok.str();
-
- GET_TOK(tok, lex);
- if( generic_mode == PATH_GENERIC_TYPE )
- {
- if( tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT )
- {
- // HACK! Handle breaking << into < <
- if( tok.type() == TOK_DOUBLE_LT )
- lex.putback( Token(TOK_LT) );
-
- // Type-mode generics "::path::to::Type<A,B>"
- params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
- }
- // HACK - 'Fn*(...) -> ...' notation
- else if( tok.type() == TOK_PAREN_OPEN )
- {
- DEBUG("Fn() hack");
- ::std::vector<TypeRef> args;
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- {
- // Empty list
- }
- else
- {
- lex.putback(tok);
- do {
- args.push_back( Parse_Type(lex) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- }
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
-
- TypeRef ret_type = TypeRef( TypeRef::TagUnit() );
- if( GET_TOK(tok, lex) == TOK_THINARROW ) {
- ret_type = Parse_Type(lex);
- }
- else {
- lex.putback(tok);
- }
- DEBUG("- Fn("<<args<<")->"<<ret_type<<"");
-
- // Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C>
- params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), ::std::move(args)) };
- // TODO: Use 'ret_type' as an associated type bound
-
- GET_TOK(tok, lex);
- }
- else
- {
- }
- }
- if( tok.type() != TOK_DOUBLE_COLON ) {
- path.append( AST::PathNode(component, params) );
- break;
- }
- tok = lex.getToken();
- if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) )
- {
- // HACK! Handle breaking << into < <
- if( tok.type() == TOK_DOUBLE_LT )
- lex.putback( Token(TOK_LT) );
-
- // Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"
- params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
- if( tok.type() != TOK_DOUBLE_COLON ) {
- path.append( AST::PathNode(component, params) );
- break;
- }
- GET_TOK(tok, lex);
- }
- path.append( AST::PathNode(component, params) );
- }
- lex.putback(tok);
- DEBUG("path = " << path);
- return path;
-}
-/// Parse a list of parameters within a path
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector<TypeRef> types;
- ::std::vector< ::std::string> lifetimes;
- ::std::map< ::std::string, TypeRef> assoc_bounds;
- ::std::vector<unsigned int> int_args;
- do {
- switch(GET_TOK(tok, lex))
- {
- case TOK_LIFETIME:
- lifetimes.push_back( tok.str() );
- break;
- case TOK_IDENT:
- if( LOOK_AHEAD(lex) == TOK_EQUAL )
- {
- ::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) );
- break;
- }
- default:
- lex.putback(tok);
- types.push_back( Parse_Type(lex) );
- break;
- }
- } while( GET_TOK(tok, lex) == TOK_COMMA );
-
- // HACK: Split >> into >
- if(tok.type() == TOK_DOUBLE_GT) {
- lex.putback(Token(TOK_GT));
- }
- else {
- CHECK_TOK(tok, TOK_GT);
- }
-
- // TODO: Actually use the lifetimes/assoc_bounds
-
- return types;
-}
-
-static const struct {
- const char* name;
- enum eCoreType type;
-} CORETYPES[] = {
- {"char", CORETYPE_CHAR},
- {"f32", CORETYPE_F32},
- {"f64", CORETYPE_F64},
- {"i16", CORETYPE_I16},
- {"i32", CORETYPE_I32},
- {"i64", CORETYPE_I64},
- {"i8", CORETYPE_I8},
- {"int", CORETYPE_INT},
- {"isize", CORETYPE_INT},
- {"u16", CORETYPE_U16},
- {"u32", CORETYPE_U32},
- {"u64", CORETYPE_U64},
- {"u8", CORETYPE_U8},
- {"uint", CORETYPE_UINT},
- {"usize", CORETYPE_UINT},
-};
-
-TypeRef Parse_Type(TokenStream& lex);
-TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi);
-
-TypeRef Parse_Type(TokenStream& lex)
-{
- //TRACE_FUNCTION;
-
- Token tok;
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_UNDERSCORE:
- return TypeRef();
- case TOK_RWORD_EXTERN: {
- GET_CHECK_TOK(tok, lex, TOK_STRING);
- ::std::string abi = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
- return Parse_Type_Fn(lex, abi);
- }
- case TOK_RWORD_FN:
- return Parse_Type_Fn(lex, "");
- case TOK_LT: {
- DEBUG("Associated type");
- // <Type as Trait>::Inner
- TypeRef base = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
- TypeRef trait = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- // TODO: Is just '<Type as Trait>' valid?
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string inner_name = tok.str();
- return TypeRef(TypeRef::TagAssoc(), ::std::move(base), ::std::move(trait), ::std::move(inner_name));
- }
- case TOK_IDENT:
- // Either a path (with generics)
- if( tok.str() == "_" )
- return TypeRef();
- // or a primitive
- for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++)
- {
- if( tok.str() < CORETYPES[i].name )
- break;
- if( tok.str() == CORETYPES[i].name )
- return TypeRef(TypeRef::TagPrimitive(), CORETYPES[i].type);
- }
- lex.putback(tok);
- return TypeRef(TypeRef::TagPath(), Parse_Path(lex, false, PATH_GENERIC_TYPE)); // relative path
- case TOK_DOUBLE_COLON:
- // Path with generics
- return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE));
- case TOK_RWORD_SUPER:
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- return TypeRef(TypeRef::TagPath(), Parse_PathFrom(lex, AST::Path(AST::Path::TagSuper()), PATH_GENERIC_TYPE));
-
- // HACK! Convert && into & &
- case TOK_DOUBLE_AMP:
- lex.putback(Token(TOK_AMP));
- case TOK_AMP: {
- ::std::string lifetime;
- // Reference
- tok = lex.getToken();
- if( tok.type() == TOK_LIFETIME ) {
- lifetime = tok.str();
- tok = lex.getToken();
- }
- if( tok.type() == TOK_RWORD_MUT ) {
- // Mutable reference
- return TypeRef(TypeRef::TagReference(), true, Parse_Type(lex));
- }
- else {
- lex.putback(tok);
- // Immutable reference
- return TypeRef(TypeRef::TagReference(), false, Parse_Type(lex));
- }
- throw ParseError::BugCheck("Reached end of Parse_Type:AMP");
- }
- case TOK_STAR:
- // Pointer
- switch( GET_TOK(tok, lex) )
- {
- case TOK_RWORD_MUT:
- // Mutable pointer
- return TypeRef(TypeRef::TagPointer(), true, Parse_Type(lex));
- case TOK_RWORD_CONST:
- // Immutable pointer
- return TypeRef(TypeRef::TagPointer(), false, Parse_Type(lex));
- default:
- throw ParseError::Unexpected(lex, tok, Token(TOK_RWORD_CONST));
- }
- throw ParseError::BugCheck("Reached end of Parse_Type:STAR");
- case TOK_SQUARE_OPEN: {
- // Array
- TypeRef inner = Parse_Type(lex);
- if( GET_TOK(tok, lex) == TOK_SEMICOLON ) {
- // Sized array
- AST::Expr array_size = Parse_Expr(lex, true);
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- return TypeRef(TypeRef::TagSizedArray(), inner, array_size.take_node());
- }
- else if( tok.type() == TOK_SQUARE_CLOSE )
- {
- return TypeRef(TypeRef::TagUnsizedArray(), inner);
- }
- else {
- throw ParseError::Unexpected(lex, tok/*, "; or ]"*/);
- }
- }
- case TOK_PAREN_OPEN: {
- DEBUG("Tuple");
- ::std::vector<TypeRef> types;
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- return TypeRef(TypeRef::TagTuple(), types);
- lex.putback(tok);
- do
- {
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- break;
- else
- lex.putback(tok);
- types.push_back(Parse_Type(lex));
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return TypeRef(TypeRef::TagTuple(), types); }
- case TOK_EXCLAM:
- throw ParseError::Generic(lex, "! is not a real type");
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- throw ParseError::BugCheck("Reached end of Parse_Type");
-}
-
-TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector<TypeRef> args;
- GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
- while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE )
- {
- args.push_back( Parse_Type(lex) );
- if( GET_TOK(tok, lex) != TOK_COMMA ) {
- lex.putback(tok);
- break;
- }
- }
- GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
-
- TypeRef ret_type = TypeRef(TypeRef::TagUnit());
- if( GET_TOK(tok, lex) == TOK_THINARROW )
- {
- ret_type = Parse_Type(lex);
- }
- else {
- lex.putback(tok);
- }
-
- return TypeRef(TypeRef::TagFunction(), ::std::move(abi), ::std::move(args), ::std::move(ret_type));
-}
-
/// Parse type parameters in a definition
void Parse_TypeBound(TokenStream& lex, AST::TypeParams& ret, TypeRef checked_type)
{
@@ -383,6 +32,7 @@ void Parse_TypeBound(TokenStream& lex, AST::TypeParams& ret, TypeRef checked_typ lex.putback(tok);
}
+/// Parse type parameters within '<' and '>' (definition)
AST::TypeParams Parse_TypeParams(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -430,17 +80,23 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex) return ret;
}
+
+/// Parse the contents of a 'where' clause
void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params)
{
TRACE_FUNCTION;
Token tok;
do {
- if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_BRACE_OPEN ) {
+ break;
+ }
+
+ if( tok.type() == TOK_LIFETIME )
{
+ throw ParseError::Todo(lex, "Lifetime bounds in 'where' clauses");
}
- else if( tok.type() == TOK_BRACE_OPEN )
- break;
else
{
lex.putback(tok);
@@ -460,7 +116,17 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params) AST::Pattern pat;
- if( expect_named || LOOK_AHEAD(lex) == TOK_UNDERSCORE || LOOK_AHEAD(lex) == TOK_RWORD_MUT || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) )
+ // If any of the following
+ // - Expecting a named parameter (i.e. defining a function in root or impl)
+ // - Next token is an underscore (only valid as a pattern here)
+ // - Next token is 'mut' (a mutable parameter slot)
+ // - Next two are <ident> ':' (a trivial named parameter)
+ // NOTE: When not expecting a named param, destructuring patterns are not allowed
+ if( expect_named
+ || LOOK_AHEAD(lex) == TOK_UNDERSCORE
+ || LOOK_AHEAD(lex) == TOK_RWORD_MUT
+ || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON)
+ )
{
pat = Parse_Pattern(lex);
GET_CHECK_TOK(tok, lex, TOK_COLON);
@@ -1464,7 +1130,7 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_it void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
{
//TRACE_FUNCTION;
- const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;'
+ const bool nested_module = (path == "-" || path == "!"); // 'mod name { code }', as opposed to 'mod name;'
Token tok;
for(;;)
@@ -1687,7 +1353,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, break; }
case TOK_SEMICOLON:
DEBUG("Mod = " << name << ", curpath = " << path);
- if( path == "-" || path == "!" ) {
+ if( nested_module ) {
throw ParseError::Generic(lex, "Cannot load module from file within nested context");
}
else if( path.back() != '/' )
diff --git a/src/parse/types.cpp b/src/parse/types.cpp new file mode 100644 index 00000000..b9cf3cc1 --- /dev/null +++ b/src/parse/types.cpp @@ -0,0 +1,221 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * parse/types.cpp + * - Parsing for type usages + */ +#include "common.hpp" +#include "parseerror.hpp" +#include "../types.hpp" +#include "../ast/ast.hpp" + +/// Mappings from internal type names to the core type enum +static const struct { + const char* name; + enum eCoreType type; +} CORETYPES[] = { + {"char", CORETYPE_CHAR}, + {"f32", CORETYPE_F32}, + {"f64", CORETYPE_F64}, + {"i16", CORETYPE_I16}, + {"i32", CORETYPE_I32}, + {"i64", CORETYPE_I64}, + {"i8", CORETYPE_I8}, + {"int", CORETYPE_INT}, + {"isize", CORETYPE_INT}, + {"u16", CORETYPE_U16}, + {"u32", CORETYPE_U32}, + {"u64", CORETYPE_U64}, + {"u8", CORETYPE_U8}, + {"uint", CORETYPE_UINT}, + {"usize", CORETYPE_UINT}, +}; + +// === PROTOTYPES === +TypeRef Parse_Type(TokenStream& lex); +TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi); + +// === CODE === +TypeRef Parse_Type(TokenStream& lex) +{ + //TRACE_FUNCTION; + + Token tok; + + switch( GET_TOK(tok, lex) ) + { + // '_' = Wildcard (type inferrence variable) + case TOK_UNDERSCORE: + return TypeRef(); + // 'extern' - A function type with an ABI + case TOK_RWORD_EXTERN: { + GET_CHECK_TOK(tok, lex, TOK_STRING); + ::std::string abi = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); + return Parse_Type_Fn(lex, abi); + } + // 'fn' - Rust function + case TOK_RWORD_FN: + return Parse_Type_Fn(lex, ""); + // '<' - An associated type cast + case TOK_LT: { + DEBUG("Associated type"); + // <Type as Trait>::Inner + TypeRef base = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); + TypeRef trait = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + // TODO: Is just '<Type as Trait>' valid? + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string inner_name = tok.str(); + return TypeRef(TypeRef::TagAssoc(), ::std::move(base), ::std::move(trait), ::std::move(inner_name)); + } + // <ident> - Either a primitive, or a path + case TOK_IDENT: + // or a primitive + for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++) + { + if( tok.str() < CORETYPES[i].name ) + break; + if( tok.str() == CORETYPES[i].name ) + return TypeRef(TypeRef::TagPrimitive(), CORETYPES[i].type); + } + lex.putback(tok); + return TypeRef(TypeRef::TagPath(), Parse_Path(lex, false, PATH_GENERIC_TYPE)); // relative path + // '::' - Absolute path + case TOK_DOUBLE_COLON: + // Path with generics + return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE)); + // 'super' - Parent relative path + case TOK_RWORD_SUPER: + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + return TypeRef(TypeRef::TagPath(), Parse_PathFrom(lex, AST::Path(AST::Path::TagSuper()), PATH_GENERIC_TYPE)); + + // HACK! Convert && into & & + case TOK_DOUBLE_AMP: + lex.putback(Token(TOK_AMP)); + // '&' - Reference type + case TOK_AMP: { + ::std::string lifetime; + // Reference + tok = lex.getToken(); + if( tok.type() == TOK_LIFETIME ) { + lifetime = tok.str(); + tok = lex.getToken(); + } + if( tok.type() == TOK_RWORD_MUT ) { + // Mutable reference + return TypeRef(TypeRef::TagReference(), true, Parse_Type(lex)); + } + else { + lex.putback(tok); + // Immutable reference + return TypeRef(TypeRef::TagReference(), false, Parse_Type(lex)); + } + throw ParseError::BugCheck("Reached end of Parse_Type:AMP"); + } + // '*' - Raw pointer + case TOK_STAR: + // Pointer + switch( GET_TOK(tok, lex) ) + { + case TOK_RWORD_MUT: + // Mutable pointer + return TypeRef(TypeRef::TagPointer(), true, Parse_Type(lex)); + case TOK_RWORD_CONST: + // Immutable pointer + return TypeRef(TypeRef::TagPointer(), false, Parse_Type(lex)); + default: + throw ParseError::Unexpected(lex, tok, Token(TOK_RWORD_CONST)); + } + throw ParseError::BugCheck("Reached end of Parse_Type:STAR"); + // '[' - Array type + case TOK_SQUARE_OPEN: { + // Array + TypeRef inner = Parse_Type(lex); + if( GET_TOK(tok, lex) == TOK_SEMICOLON ) { + // Sized array + AST::Expr array_size = Parse_Expr(lex, true); + GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); + return TypeRef(TypeRef::TagSizedArray(), inner, array_size.take_node()); + } + else if( tok.type() == TOK_SQUARE_CLOSE ) + { + return TypeRef(TypeRef::TagUnsizedArray(), inner); + } + else { + throw ParseError::Unexpected(lex, tok/*, "; or ]"*/); + } + } + + // '(' - Tuple (or lifetime bounded trait) + case TOK_PAREN_OPEN: { + DEBUG("Tuple"); + if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) + return TypeRef(TypeRef::TagTuple(), {}); + lex.putback(tok); + + TypeRef inner = Parse_Type(lex); + if( GET_TOK(tok, lex) == TOK_PLUS ) + { + // Lifetime bounded type, NOT a tuple + GET_CHECK_TOK(tok, lex, TOK_LIFETIME); + ::std::string lifetime = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + throw ParseError::Todo(lex, "Type lifetime bounds"); + } + else + { + ::std::vector<TypeRef> types; + types.push_back( ::std::move(inner) ); + lex.putback(tok); + while( GET_TOK(tok, lex) == TOK_COMMA ) + { + if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) + break; + else + lex.putback(tok); + types.push_back(Parse_Type(lex)); + } + CHECK_TOK(tok, TOK_PAREN_CLOSE); + return TypeRef(TypeRef::TagTuple(), types); } + } + case TOK_EXCLAM: + throw ParseError::Generic(lex, "! is not a real type"); + default: + throw ParseError::Unexpected(lex, tok); + } + throw ParseError::BugCheck("Reached end of Parse_Type"); +} + +TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi) +{ + TRACE_FUNCTION; + Token tok; + + ::std::vector<TypeRef> args; + GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); + while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) + { + args.push_back( Parse_Type(lex) ); + if( GET_TOK(tok, lex) != TOK_COMMA ) { + lex.putback(tok); + break; + } + } + GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + + TypeRef ret_type = TypeRef(TypeRef::TagUnit()); + if( GET_TOK(tok, lex) == TOK_THINARROW ) + { + ret_type = Parse_Type(lex); + } + else { + lex.putback(tok); + } + + return TypeRef(TypeRef::TagFunction(), ::std::move(abi), ::std::move(args), ::std::move(ret_type)); +} + |