diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 3 | ||||
-rw-r--r-- | src/ast/ast.hpp | 52 | ||||
-rw-r--r-- | src/ast/pattern.cpp | 15 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 21 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 3 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 8 | ||||
-rw-r--r-- | src/parse/common.hpp | 5 | ||||
-rw-r--r-- | src/parse/expr.cpp | 60 | ||||
-rw-r--r-- | src/parse/lex.cpp | 205 | ||||
-rw-r--r-- | src/parse/lex.hpp | 10 | ||||
-rw-r--r-- | src/parse/parseerror.cpp | 9 | ||||
-rw-r--r-- | src/parse/paths.cpp | 2 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 7 | ||||
-rw-r--r-- | src/parse/root.cpp | 291 | ||||
-rw-r--r-- | src/parse/types.cpp | 82 | ||||
-rw-r--r-- | src/types.hpp | 5 |
16 files changed, 564 insertions, 214 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 7d6185e3..c8ad705f 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -500,7 +500,8 @@ SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", { },{
})
-SERIALISE_TYPE_A(MacroItem::, "AST_MacroItem", {
+SERIALISE_TYPE_A(MacroInvocation::, "AST_MacroInvocation", {
+ s.item(m_attrs);
s.item(m_macro_name);
s.item(m_ident);
s.item(m_input);
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 9c644bf6..a703da89 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -398,6 +398,7 @@ class Trait: ::std::vector<AST::Path> m_supertraits;
ItemList<TypeAlias> m_types;
ItemList<Function> m_functions;
+ ItemList<Static> m_statics;
public:
Trait() {}
Trait(MetaItems attrs, GenericParams params, ::std::vector<Path> supertraits):
@@ -412,6 +413,7 @@ public: const ::std::vector<Path>& supertraits() const { return m_supertraits; }
const ItemList<Function>& functions() const { return m_functions; }
const ItemList<TypeAlias>& types() const { return m_types; }
+ const ItemList<Static>& statics() const { return m_statics; }
GenericParams& params() { return m_params; }
::std::vector<Path>& supertraits() { return m_supertraits; }
@@ -424,6 +426,9 @@ public: void add_function(::std::string name, Function fcn) {
m_functions.push_back( Item<Function>(::std::move(name), ::std::move(fcn), true) );
}
+ void add_static(::std::string name, Static v) {
+ m_statics.push_back( Item<Static>(mv$(name), mv$(v), true) );
+ }
bool has_named_item(const ::std::string& name, bool& out_is_fcn) const {
for( const auto& f : m_functions )
@@ -450,25 +455,31 @@ struct EnumVariant: MetaItems m_attrs;
::std::string m_name;
::std::vector<TypeRef> m_sub_types;
- int64_t m_value;
+ ::std::vector<StructItem> m_fields;
+ AST::Expr m_value;
- EnumVariant():
- m_value(0)
+ EnumVariant()
{
}
- EnumVariant(MetaItems attrs, ::std::string name, int64_t value):
+ EnumVariant(MetaItems attrs, ::std::string name, Expr&& value):
+ m_attrs( mv$(attrs) ),
+ m_name( mv$(name) ),
+ m_value( mv$(value) )
+ {
+ }
+
+ EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<TypeRef> sub_types):
m_attrs( move(attrs) ),
m_name( ::std::move(name) ),
- m_value( value )
+ m_sub_types( ::std::move(sub_types) )
{
}
- EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<TypeRef> sub_types):
+ EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<StructItem> fields):
m_attrs( move(attrs) ),
m_name( ::std::move(name) ),
- m_sub_types( ::std::move(sub_types) ),
- m_value(0)
+ m_fields( ::std::move(fields) )
{
}
@@ -571,6 +582,7 @@ class Impl: ItemList<TypeRef> m_types;
ItemList<Function> m_functions;
+ ItemList<Static> m_statics;
::std::vector< ::std::pair< ::std::vector<TypeRef>, Impl > > m_concrete_impls;
public:
@@ -586,6 +598,9 @@ public: void add_type(bool is_public, ::std::string name, TypeRef type) {
m_types.push_back( Item<TypeRef>( ::std::move(name), ::std::move(type), is_public ) );
}
+ void add_static(bool is_public, ::std::string name, Static v) {
+ m_statics.push_back( Item<Static>( mv$(name), mv$(v), is_public ) );
+ }
const ImplDef& def() const { return m_def; }
const ItemList<Function>& functions() const { return m_functions; }
@@ -615,7 +630,7 @@ class Module; typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Function& fcn);
-class MacroItem:
+class MacroInvocation:
public Serialisable
{
MetaItems m_attrs;
@@ -623,11 +638,11 @@ class MacroItem: ::std::string m_ident;
TokenTree m_input;
public:
- MacroItem()
+ MacroInvocation()
{
}
- MacroItem(MetaItems attrs, ::std::string macro, ::std::string ident, TokenTree input):
+ MacroInvocation(MetaItems attrs, ::std::string macro, ::std::string ident, TokenTree input):
m_attrs( mv$(attrs) ),
m_macro_name( mv$(macro) ),
m_ident( mv$(ident) ),
@@ -635,7 +650,18 @@ public: {
}
+ static ::std::unique_ptr<MacroInvocation> from_deserialiser(Deserialiser& s) {
+ auto i = new MacroInvocation;
+ s.item( *i );
+ return ::std::unique_ptr<MacroInvocation>(i);
+ }
+
SERIALISABLE_PROTOTYPES();
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const MacroInvocation& x) {
+ os << x.m_attrs << x.m_macro_name << "! " << x.m_ident << x.m_input;
+ return os;
+ }
};
/// Representation of a parsed (and being converted) function
@@ -664,7 +690,7 @@ class Module: itemlist_macros_t m_macros;
macro_imports_t m_macro_imports; // module => macro
::std::vector< ItemNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
- ::std::vector<MacroItem> m_macro_invocations;
+ ::std::vector<MacroInvocation> m_macro_invocations;
@@ -728,7 +754,7 @@ public: m_macros.push_back( Item<MacroRules>( move(name), move(macro), is_exported ) );
}
void add_macro_import(const Crate& crate, ::std::string mod, ::std::string name);
- void add_macro_invocation(MacroItem item) {
+ void add_macro_invocation(MacroInvocation item) {
m_macro_invocations.push_back( mv$(item) );
}
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp index f2279a55..7ebdb35d 100644 --- a/src/ast/pattern.cpp +++ b/src/ast/pattern.cpp @@ -15,12 +15,15 @@ namespace AST { { os << "Pattern(" << pat.m_binding << " @ "; TU_MATCH(Pattern::Data, (pat.m_data), (ent), - (Any, - os << "_"; - ), (MaybeBind, os << "?"; ), + (Macro, + os << *ent.inv; + ), + (Any, + os << "_"; + ), (Box, os << "box " << *ent.sub; ), @@ -62,6 +65,9 @@ SERIALISE_TYPE(Pattern::, "Pattern", { ), (MaybeBind, ), + (Macro, + s.item( e.inv ); + ), (Box, s << e.sub; ), @@ -94,6 +100,9 @@ SERIALISE_TYPE(Pattern::, "Pattern", { _D(Any, ) _D(MaybeBind, ) + _D(Macro, + s.item( ent.inv ); + ) _D(Box, s.item( ent.sub ); ) diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index f28fe8e3..6cd78e91 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -11,6 +11,7 @@ namespace AST { using ::std::unique_ptr; using ::std::move; +class MacroInvocation; class ExprNode; @@ -19,8 +20,9 @@ class Pattern: { public: TAGGED_UNION(Data, Any, - (Any, () ), (MaybeBind, () ), + (Macro, (unique_ptr<::AST::MacroInvocation> inv;) ), + (Any, () ), (Box, (unique_ptr<Pattern> sub;) ), (Ref, (bool mut; unique_ptr<Pattern> sub;) ), (Value, (unique_ptr<ExprNode> start; unique_ptr<ExprNode> end;) ), @@ -36,6 +38,17 @@ public: Pattern() {} + struct TagMaybeBind {}; + Pattern(TagMaybeBind, ::std::string name): + m_binding(name), + m_data( Data::make_MaybeBind({}) ) + {} + + struct TagMacro {}; + Pattern(TagMacro, unique_ptr<::AST::MacroInvocation> inv): + m_data( Data::make_Macro({mv$(inv)}) ) + {} + // Wildcard = '..', distinct from '_' // TODO: Store wildcard as a different pattern type struct TagWildcard {}; @@ -47,12 +60,6 @@ public: m_binding(name) {} - struct TagMaybeBind {}; - Pattern(TagMaybeBind, ::std::string name): - m_binding(name), - m_data( Data::make_MaybeBind({}) ) - {} - struct TagBox {}; Pattern(TagBox, Pattern sub): m_data( Data::make_Box({ unique_ptr<Pattern>(new Pattern(mv$(sub))) }) ) diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 3674d947..f5bc805e 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -123,6 +123,9 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) (Any, // Wildcard, nothing to do ), + (Macro, + // Macro, nothing really (should be impossible?) + ), (Box, { auto& v = pat.data().as_Box(); if( type_hint.is_wildcard() ) diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index a498e626..f7f1d30b 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -746,6 +746,9 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) (MaybeBind, m_os << "_ /*?*/"; ), + (Macro, + m_os << *v.inv; + ), (Box, { const auto& v = p.data().as_Box(); m_os << "& "; @@ -854,10 +857,13 @@ void RustPrinter::handle_enum(const AST::Enum& s) for( const auto& t : i.m_sub_types ) m_os << t.print_pretty() << ", "; } - else if(i.m_value > 0) + else if(i.m_value.is_valid()) { m_os << " = " << i.m_value; } + else + { + } m_os << ",\n"; idx ++; } diff --git a/src/parse/common.hpp b/src/parse/common.hpp index e24ef82b..def771e2 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -39,13 +39,18 @@ extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex); extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
+extern ::AST::MacroInvocation Parse_MacroInvocation(::AST::MetaItems meta_items, ::std::string name, TokenStream& lex);
extern TypeRef Parse_Type(TokenStream& lex);
extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable);
extern void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn);
extern AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items);
+extern AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items);
+extern AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items);
extern void Parse_Impl(TokenStream& lex, AST::Module& mod, bool is_unsafe=false);
extern void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items);
+extern void Parse_ExternCrate(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items);
+
extern AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype);
extern AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 47fe444a..723352d3 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -93,7 +93,13 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) // 'extern' blocks
case TOK_RWORD_EXTERN:
keep_mod = true;
- Parse_ExternBlock(lex, ::std::move(item_attrs), local_mod->functions());
+ if( GET_TOK(tok, lex) == TOK_RWORD_CRATE ) {
+ Parse_ExternCrate(lex, *local_mod, mv$(item_attrs));
+ }
+ else {
+ lex.putback(tok);
+ Parse_ExternBlock(lex, ::std::move(item_attrs), local_mod->functions());
+ }
break;
// - 'const'
case TOK_RWORD_CONST:
@@ -142,6 +148,20 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) ::std::string name = tok.str();
local_mod->add_struct(false, mv$(name), Parse_Struct(lex, item_attrs));
break; }
+ // - 'enum'
+ case TOK_RWORD_ENUM: {
+ keep_mod = true;
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ local_mod->add_enum(false, mv$(name), Parse_EnumDef(lex, item_attrs));
+ break; }
+ // - 'trait'
+ case TOK_RWORD_TRAIT: {
+ keep_mod = true;
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = tok.str();
+ local_mod->add_trait(false, mv$(name), Parse_TraitDef(lex, mv$(item_attrs)));
+ break; }
// - 'impl'
case TOK_RWORD_IMPL:
keep_mod = true;
@@ -306,8 +326,9 @@ void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AS if( GET_TOK(tok, lex) == TOK_STRING ) {
abi = tok.str();
}
- else
+ else {
lex.putback(tok);
+ }
bool is_block = false;
if( GET_TOK(tok, lex) == TOK_BRACE_OPEN ) {
@@ -507,8 +528,17 @@ ExprNodeP Parse_Stmt(TokenStream& lex) {
case TOK_RWORD_RETURN: {
ExprNodeP val;
- if( LOOK_AHEAD(lex) != TOK_SEMICOLON && LOOK_AHEAD(lex) != TOK_COMMA && LOOK_AHEAD(lex) != TOK_BRACE_CLOSE ) {
+ switch(LOOK_AHEAD(lex))
+ {
+ case TOK_SEMICOLON:
+ case TOK_COMMA:
+ case TOK_BRACE_CLOSE:
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ break;
+ default:
val = Parse_Expr1(lex);
+ break;
}
return NEWNODE( AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", ::std::move(val) );
}
@@ -529,14 +559,22 @@ ExprNodeP Parse_Stmt(TokenStream& lex) GET_TOK(tok, lex);
}
ExprNodeP val;
- if( tok.type() != TOK_SEMICOLON && tok.type() != TOK_COMMA && tok.type() != TOK_BRACE_CLOSE ) {
+ switch(tok.type())
+ {
+ case TOK_SEMICOLON:
+ case TOK_COMMA:
+ case TOK_BRACE_CLOSE:
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ lex.putback(tok);
+ break;
+ default:
lex.putback(tok);
val = Parse_Expr1(lex);
+ break;
}
- else
- lex.putback(tok);
return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) );
- }
+ }
default:
lex.putback(tok);
return Parse_Expr0(lex);
@@ -556,7 +594,7 @@ ExprNodeP Parse_Stmt(TokenStream& lex) {
lex.putback(tok);
do {
- rv.push_back( Parse_Expr0(lex) );
+ rv.push_back( Parse_Stmt(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
}
@@ -598,7 +636,7 @@ ExprNodeP Parse_Expr0(TokenStream& lex) case TOK_EQUAL:
op = AST::ExprNode_Assign::NONE;
- return NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr1(lex) );
+ return NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr0(lex) );
default:
lex.putback(tok);
@@ -1091,7 +1129,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
lex.putback(tok);
- ExprNodeP rv = Parse_Expr0(lex);
+ ExprNodeP rv = Parse_Stmt(lex);
if( GET_TOK(tok, lex) == TOK_COMMA ) {
::std::vector<ExprNodeP> ents;
ents.push_back( ::std::move(rv) );
@@ -1099,7 +1137,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
break;
lex.putback(tok);
- ents.push_back( Parse_Expr0(lex) );
+ ents.push_back( Parse_Stmt(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
}
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 2338adcd..dc206ad8 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -200,12 +200,14 @@ signed int Lexer::getSymbol() return best; } -bool issym(char ch) +bool issym(int ch) { if( ::std::isalnum(ch) ) return true; if( ch == '_' ) return true; + if( ch >= 128 || ch < 0 ) + return true; return false; } @@ -279,7 +281,7 @@ Token Lexer::getTokenInt() uint64_t val = 0; if( ch == '0' ) { // Octal/hex handling - ch = this->getc(); + ch = this->getc_num(); if( ch == 'x' ) { num_mode = HEX; while( isxdigit(ch = this->getc_num()) ) @@ -323,7 +325,7 @@ Token Lexer::getTokenInt() } } - if(ch == 'u' || ch == 'i') { + if(issym(ch)) { // Unsigned ::std::string suffix; while( issym(ch) ) @@ -344,6 +346,8 @@ Token Lexer::getTokenInt() else if(suffix == "u32") num_type = CORETYPE_U32; else if(suffix == "u64") num_type = CORETYPE_U64; else if(suffix == "usize") num_type = CORETYPE_UINT; + else if(suffix == "f32") num_type = CORETYPE_F32; + else if(suffix == "f64") num_type = CORETYPE_F64; else throw ParseError::Generic(*this, FMT("Unknown integer suffix '" << suffix << "'")); return Token(val, num_type); @@ -375,7 +379,7 @@ Token Lexer::getTokenInt() this->ungetc(); double fval = this->parseFloat(val); - if( (ch = this->getc()) == 'f' ) + if( issym(ch = this->getc()) ) { ::std::string suffix; while( issym(ch) ) @@ -403,62 +407,60 @@ Token Lexer::getTokenInt() return Token(val, num_type); } } - // Symbols - else if( issym(ch) ) + // Byte/Raw strings + else if( ch == 'b' || ch == 'r' ) { - ::std::string str; - while( issym(ch) ) - { - str.push_back(ch); + bool is_byte = false; + if(ch == 'b') { + is_byte = true; ch = this->getc(); } - - if( ch == '!' ) - { - return Token(TOK_MACRO, str); + + if(ch == 'r') { + return this->getTokenInt_RawString(is_byte); } - else - { - if( str == "b" ) - { - if( ch == '\'' ) { - // Byte constant - ch = this->getc(); - if( ch == '\\' ) { - uint32_t val = this->parseEscape('\''); - if( this->getc() != '\'' ) - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)val, CORETYPE_U8); - } - else { - if( this->getc() != '\'' ) - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)ch, CORETYPE_U8); - } + else { + assert(is_byte); + + // Byte string + if( ch == '"' ) { + ::std::string str; + while( (ch = this->getc()) != '"' ) + { + if( ch == '\\' ) + ch = this->parseEscape('"'); + str.push_back(ch); } - else if( ch == '"') { - ::std::string str; - while( (ch = this->getc()) != '"' ) - { - if( ch == '\\' ) - ch = this->parseEscape('"'); - str.push_back(ch); - } - return Token(TOK_BYTESTRING, str); + return Token(TOK_BYTESTRING, str); + } + // Byte constant + else if( ch == '\'' ) { + // Byte constant + ch = this->getc(); + if( ch == '\\' ) { + uint32_t val = this->parseEscape('\''); + if( this->getc() != '\'' ) + throw ParseError::Generic(*this, "Multi-byte character literal"); + return Token((uint64_t)val, CORETYPE_U8); } else { + if( this->getc() != '\'' ) + throw ParseError::Generic(*this, "Multi-byte character literal"); + return Token((uint64_t)ch, CORETYPE_U8); } } - - this->ungetc(); - for( unsigned int i = 0; i < LEN(RWORDS); i ++ ) - { - if( str < RWORDS[i].chars ) break; - if( str == RWORDS[i].chars ) return Token((enum eTokenType)RWORDS[i].type); + else { + assert(is_byte); + this->ungetc(); + return this->getTokenInt_Identifier('b'); } - return Token(TOK_IDENT, str); } } + // Symbols + else if( issym(ch) ) + { + return this->getTokenInt_Identifier(ch); + } else { throw ParseError::BadChar(ch); @@ -497,17 +499,25 @@ Token Lexer::getTokenInt() } return Token(TOK_COMMENT, str); } case SINGLEQUOTE: { - char firstchar = this->getc(); - if( firstchar != '\\' ) { + auto firstchar = this->getc_codepoint(); + if( firstchar.v == '\\' ) { + // Character constant with an escape code + uint32_t val = this->parseEscape('\''); + if(this->getc() != '\'') { + throw ParseError::Todo("Proper error for lex failures"); + } + return Token((uint64_t)val, CORETYPE_CHAR); + } + else { ch = this->getc(); if( ch == '\'' ) { // Character constant - return Token((uint64_t)firstchar, CORETYPE_CHAR); + return Token((uint64_t)firstchar.v, CORETYPE_CHAR); } - else { + else if( issym(firstchar.v) ) { // Lifetime name ::std::string str; - str.push_back(firstchar); + str += firstchar; while( issym(ch) ) { str.push_back(ch); @@ -516,14 +526,9 @@ Token Lexer::getTokenInt() this->ungetc(); return Token(TOK_LIFETIME, str); } - } - else { - // Character constant with an escape code - uint32_t val = this->parseEscape('\''); - if(this->getc() != '\'') { - throw ParseError::Todo("Proper error for lex failures"); + else { + throw ParseError::Todo("Lex Fail - Expected ' after character constant"); } - return Token((uint64_t)val, CORETYPE_CHAR); } break; } case DOUBLEQUOTE: { @@ -548,6 +553,72 @@ Token Lexer::getTokenInt() //assert(!"bugcheck"); } +Token Lexer::getTokenInt_RawString(bool is_byte) +{ + // Raw string (possibly byte) + char ch = this->getc(); + unsigned int hashes = 0; + while(ch == '#') + { + hashes ++; + ch = this->getc(); + } + if( hashes == 0 && ch != '"' ) { + this->ungetc(); + return this->getTokenInt_Identifier('r'); + } + char terminator = ch; + ::std::string val; + + for(;;) + { + ch = this->getc(); + if( ch == terminator ) { + for(unsigned i = 0; i < hashes; i ++) + { + ch = this->getc(); + if( ch != '#' ) { + val += terminator; + while( i -- ) + val += '#'; + break ; + } + } + if( hashes == 0 || ch == '#' ) { + return Token(is_byte ? TOK_BYTESTRING : TOK_STRING, val); + } + } + else { + val += ch; + } + } +} +Token Lexer::getTokenInt_Identifier(char leader) +{ + char ch = leader; + ::std::string str; + while( issym(ch) ) + { + str.push_back(ch); + ch = this->getc(); + } + + if( ch == '!' ) + { + return Token(TOK_MACRO, str); + } + else + { + this->ungetc(); + for( unsigned int i = 0; i < LEN(RWORDS); i ++ ) + { + if( str < RWORDS[i].chars ) break; + if( str == RWORDS[i].chars ) return Token((enum eTokenType)RWORDS[i].type); + } + return Token(TOK_IDENT, str); + } +} + // Takes the VERY lazy way of reading the float into a string then passing to strtod double Lexer::parseFloat(uint64_t whole) { @@ -615,6 +686,8 @@ uint32_t Lexer::parseEscape(char enclosing) else ; return val; } + case '0': + return '\0'; case '\\': return '\\'; case '\'': @@ -628,7 +701,7 @@ uint32_t Lexer::parseEscape(char enclosing) case 't': return '\t'; case '\n': - m_line ++; + m_line ++; while( isspace(ch) ) ch = this->getc(); return ch; @@ -662,6 +735,16 @@ char Lexer::getc_num() } while( ch == '_' ); return ch; } +Codepoint Lexer::getc_codepoint() +{ + uint8_t v1 = this->getc(); + if( v1 < 128 ) { + return {v1}; + } + else { + throw ParseError::Todo("getc_codepoint"); + } +} void Lexer::ungetc() { diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index 30500ba2..1b37127e 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -172,6 +172,13 @@ public: #define CLEAR_PARSE_FLAG(lex, flag) SavedParseState _sps(lex, lex.parse_state()); lex.parse_state().flag = false #define CHECK_PARSE_FLAG(lex, flag) (lex.parse_state().flag == true) +struct Codepoint { + uint32_t v; + friend ::std::string& operator+=(::std::string& s, const Codepoint& cp) { + return s; + } +}; + class Lexer: public TokenStream { @@ -193,11 +200,14 @@ private: Token getTokenInt(); signed int getSymbol(); + Token getTokenInt_RawString(bool is_byte); + Token getTokenInt_Identifier(char ch); double parseFloat(uint64_t whole); uint32_t parseEscape(char enclosing); char getc(); char getc_num(); + Codepoint getc_codepoint(); void ungetc(); class EndOfFile {}; diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp index 0d58bd52..bd9d5a7c 100644 --- a/src/parse/parseerror.cpp +++ b/src/parse/parseerror.cpp @@ -78,7 +78,14 @@ ParseError::Unexpected::Unexpected(const TokenStream& lex, Token tok, ::std::vec if(pos.filename == "")
pos = lex.getPosition();
::std::cout << pos << ": Unexpected " << tok << ", expected ";
- ::std::cout << exp << ")" << ::std::endl;
+ bool f = true;
+ for(auto v: exp) {
+ if(!f)
+ ::std::cout << " or ";
+ f = false;
+ ::std::cout << Token::typestr(v);
+ }
+ ::std::cout << ::std::endl;
}
ParseError::Unexpected::~Unexpected() throw()
{
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index f867e244..1b48dbb3 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -21,6 +21,8 @@ AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode) { case TOK_DOUBLE_COLON: return Parse_Path(lex, true, generic_mode); + case TOK_DOUBLE_LT: + lex.putback( Token(TOK_LT) ); case TOK_LT: { TypeRef ty = Parse_Type(lex); TypeRef trait; diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index 32d1b017..4e4fa862 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -37,6 +37,11 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) Token tok; tok = lex.getToken(); + if( tok.type() == TOK_MACRO ) + { + return AST::Pattern( AST::Pattern::TagMacro(), box$(Parse_MacroInvocation(AST::MetaItems(), tok.str(), lex))); + } + bool expect_bind = false; bool is_mut = false; bool is_ref = false; @@ -190,6 +195,8 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, false ) ); case TOK_STRING: return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) ); + case TOK_BYTESTRING: + return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) ); case TOK_PAREN_OPEN: return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable)); case TOK_SQUARE_OPEN: diff --git a/src/parse/root.cpp b/src/parse/root.cpp index fb7249e4..d9e47626 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -52,27 +52,26 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_ else if( tok.type() == TOK_QMARK ) {
ret.add_bound(AST::GenericBound::make_MaybeTrait( {type: checked_type, trait: Parse_Path(lex, PATH_GENERIC_TYPE)} ));
}
- //else if( tok.type() == TOK_RWORD_FOR )
- //{
- // ::std::vector< ::std::string> lifetimes;
- // GET_CHECK_TOK(tok, lex, TOK_LT);
- // do {
- // switch(GET_TOK(tok, lex))
- // {
- // case TOK_LIFETIME:
- // lifetimes.push_back(tok.str());
- // break;
- // default:
- // throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME));
- // }
- // } while( GET_TOK(tok, lex) == TOK_COMMA );
- // CHECK_TOK(tok, TOK_GT);
- //
- // ret.add_bound( AST::GenericBound::make_IsTrait( {type: checked_type, hrls: lifetimes, trait: Parse_Path(lex, PATH_GENERIC_TYPE) }) );
- //}
- else
- {
- lex.putback(tok);
+ else {
+ if( tok.type() == TOK_RWORD_FOR )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_LT);
+ do {
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_LIFETIME:
+ lifetimes.push_back(tok.str());
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME));
+ }
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_GT);
+ }
+ else {
+ lex.putback(tok);
+ }
+
ret.add_bound( AST::GenericBound::make_IsTrait( {type: checked_type, hrls: lifetimes, trait: Parse_Path(lex, PATH_GENERIC_TYPE) }) );
}
} while( GET_TOK(tok, lex) == TOK_PLUS );
@@ -274,7 +273,16 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt GET_TOK(tok, lex);
if( allow_self == false )
throw ParseError::Generic(lex, "Self binding not expected");
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef("Self")) );
+ TypeRef ty;
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ // Typed mut self
+ ty = Parse_Type(lex);
+ }
+ else {
+ lex.putback(tok);
+ ty = TypeRef("Self");
+ }
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), ty) );
GET_TOK(tok, lex);
}
}
@@ -283,7 +291,16 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt // By-value method
if( allow_self == false )
throw ParseError::Generic(lex, "Self binding not expected");
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef("Self")) );
+ TypeRef ty;
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ // Typed mut self
+ ty = Parse_Type(lex);
+ }
+ else {
+ lex.putback(tok);
+ ty = TypeRef("Self");
+ }
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), ty) );
GET_TOK(tok, lex);
}
else
@@ -534,7 +551,35 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) switch(tok.type())
{
case TOK_RWORD_STATIC: {
- throw ParseError::Todo("Associated static");
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex, true);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ trait.add_static( mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::STATIC, mv$(ty), val) );
+ break; }
+ case TOK_RWORD_CONST: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex, true);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ trait.add_static( mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::CONST, mv$(ty), val) );
break; }
// Associated type
case TOK_RWORD_TYPE: {
@@ -631,6 +676,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items) ::std::vector<AST::EnumVariant> variants;
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ auto sp = lex.start_span();
AST::MetaItems item_attrs;
while( tok.type() == TOK_ATTR_OPEN )
{
@@ -653,16 +699,26 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items) GET_TOK(tok, lex);
variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) );
}
+ else if( tok.type() == TOK_BRACE_OPEN )
+ {
+ ::std::vector<::AST::StructItem> fields;
+ do
+ {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ fields.push_back( ::AST::Item<TypeRef>(mv$(name), mv$(ty), true) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ GET_TOK(tok, lex);
+
+ variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) );
+ }
else if( tok.type() == TOK_EQUAL )
{
- bool is_neg = false;
- if( GET_TOK(tok, lex) == TOK_DASH )
- is_neg = true;
- else
- lex.putback(tok);
- GET_CHECK_TOK(tok, lex, TOK_INTEGER);
- int64_t val = (is_neg ? -tok.intval() : tok.intval());
- variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), val) );
+ auto node = Parse_Expr(lex, true);
+ variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) );
GET_TOK(tok, lex);
}
else
@@ -857,7 +913,16 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) case TOK_RWORD_CONST:
if( GET_TOK(tok, lex) != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE )
{
- BUG(lex.end_span(lex.start_span()), "TODO: Associated const");
+ CHECK_TOK(tok, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ auto val = Parse_Expr(lex, true);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ impl.add_static( is_public, mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::CONST, mv$(ty), mv$(val)) );
+ break ;
}
else if( tok.type() == TOK_RWORD_UNSAFE )
{
@@ -934,9 +999,13 @@ void Parse_Use_Set(TokenStream& lex, const AST::Path& base_path, ::std::function Token tok;
do {
+
if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) {
fcn(base_path, base_path[base_path.size()-1].name());
}
+ else if( tok.type() == TOK_BRACE_CLOSE ) {
+ break ;
+ }
else {
CHECK_TOK(tok, TOK_IDENT);
fcn(base_path + AST::PathNode(tok.str(), {}), tok.str());
@@ -1024,6 +1093,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> else
{
lex.putback(tok);
+ assert(path.nodes().size() > 0);
name = path.nodes().back().name();
}
@@ -1255,10 +1325,20 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_it GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+ eTokenType close;
+ switch(GET_TOK(tok,lex))
+ {
+ case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break;
+ case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break;
+ case TOK_SQUARE_OPEN: close = TOK_SQUARE_CLOSE; break;
+ default:
+ // TODO: Synerror
+ throw ParseError::Unexpected(lex, tok, {TOK_BRACE_OPEN, TOK_PAREN_OPEN, TOK_SQUARE_OPEN});
+ break;
+ }
::std::vector<MacroRule> rules;
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ while( GET_TOK(tok, lex) != close )
{
lex.putback(tok);
@@ -1274,6 +1354,68 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_it mod.add_macro( is_pub, name, MacroRules(move(rules)) );
}
+::AST::MacroInvocation Parse_MacroInvocation(::AST::MetaItems meta_items, ::std::string name, TokenStream& lex)
+{
+ Token tok;
+ ::std::string ident;
+ if( GET_TOK(tok, lex) == TOK_IDENT ) {
+ ident = mv$(tok.str());
+ }
+ else {
+ lex.putback(tok);
+ }
+ TokenTree tt = Parse_TT(lex, true);
+ return ::AST::MacroInvocation( mv$(meta_items), mv$(name), mv$(ident), mv$(tt));
+}
+
+void Parse_ExternCrate(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items)
+{
+ Token tok;
+ ::std::string path, name;
+ switch( GET_TOK(tok, lex) )
+ {
+ // `extern crate "crate-name" as crate_name;`
+ // TODO: rustc no longer supports this feature
+ case TOK_STRING:
+ path = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = tok.str();
+ break;
+ // `extern crate crate_name;`
+ case TOK_IDENT:
+ name = tok.str();
+ if(GET_TOK(tok, lex) == TOK_RWORD_AS) {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ }
+ else {
+ lex.putback(tok);
+ name = path;
+ }
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT});
+ }
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ mod.add_ext_crate(path, name);
+
+ // Handle #[macro_use]/#[macro_use(...)]
+ //auto at = meta_items.get("macro_use");
+ //if( at )
+ //{
+ // if( at->has_sub_items() )
+ // {
+ // throw ParseError::Todo("selective macro_use");
+ // }
+ // else
+ // {
+ // mod.add_macro_import(crate, name, "");
+ // }
+ //}
+}
+
void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
{
//TRACE_FUNCTION;
@@ -1309,22 +1451,14 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, {
::std::string name = mv$(tok.str());
// `macro_rules! ...`
- if( name == "macro_rules" )
- {
- Parse_MacroRules(lex, mod, mv$(meta_items));
- }
- else
- {
- ::std::string ident;
- if( GET_TOK(tok, lex) == TOK_IDENT ) {
- ident = mv$(tok.str());
- }
- else {
- lex.putback(tok);
- }
- TokenTree tt = Parse_TT(lex, true);
- mod.add_macro_invocation( ::AST::MacroItem( mv$(meta_items), mv$(name), mv$(ident), mv$(tt)) );
- }
+ //if( name == "macro_rules" )
+ //{
+ // Parse_MacroRules(lex, mod, mv$(meta_items));
+ //}
+ //else
+ //{
+ mod.add_macro_invocation( Parse_MacroInvocation( mv$(meta_items), mv$(name), lex ) );
+ //}
// - Silently consume ';' after the macro
if( GET_TOK(tok, lex) != TOK_SEMICOLON )
lex.putback(tok);
@@ -1387,44 +1521,9 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, break;
// `extern crate "crate-name" as crate_name;`
// `extern crate crate_name;`
- case TOK_RWORD_CRATE: {
- ::std::string path, name;
- switch( GET_TOK(tok, lex) )
- {
- // `extern crate "crate-name" as crate_name;`
- // TODO: rustc no longer supports this feature
- case TOK_STRING:
- path = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = tok.str();
- break;
- // `extern crate crate_name;`
- case TOK_IDENT:
- path = name = tok.str();
- break;
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT});
- }
- crate.load_extern_crate(path);
- mod.add_ext_crate(path, name);
-
- // Handle #[macro_use]/#[macro_use(...)]
- auto at = meta_items.get("macro_use");
- if( at )
- {
- if( at->has_sub_items() )
- {
- throw ParseError::Todo("selective macro_use");
- }
- else
- {
- mod.add_macro_import(crate, name, "");
- }
- }
-
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break; }
+ case TOK_RWORD_CRATE:
+ Parse_ExternCrate(lex, mod, mv$(meta_items));
+ break;
default:
throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_RWORD_FN, TOK_BRACE_OPEN, TOK_RWORD_CRATE});
}
@@ -1487,6 +1586,19 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, meta_items.push_back( AST::MetaItem("#UNSAFE") );
switch(GET_TOK(tok, lex))
{
+ // `unsafe extern fn`
+ case TOK_RWORD_EXTERN: {
+ ::std::string abi = "C";
+ if(GET_TOK(tok, lex) == TOK_STRING) {
+ abi = mv$(tok.str());
+ }
+ else {
+ lex.putback(tok);
+ }
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, abi, ::std::move(meta_items), false));
+ break; }
// `unsafe fn`
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
@@ -1498,6 +1610,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, case TOK_RWORD_TRAIT: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
+ // TODO: Mark as unsafe
mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items));
break; }
// `unsafe impl`
diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 532cccae..425a7f36 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -14,6 +14,7 @@ TypeRef Parse_Type(TokenStream& lex); TypeRef Parse_Type_Int(TokenStream& lex); TypeRef Parse_Type_Fn(TokenStream& lex); +TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls); // === CODE === TypeRef Parse_Type(TokenStream& lex) @@ -52,8 +53,26 @@ TypeRef Parse_Type_Int(TokenStream& lex) return Parse_Type_Fn(lex); // '<' - An associated type cast case TOK_LT: + case TOK_DOUBLE_LT: lex.putback(tok); return TypeRef(TypeRef::TagPath(), Parse_Path(lex, PATH_GENERIC_TYPE)); + // + case TOK_RWORD_FOR: { + GET_CHECK_TOK(tok, lex, TOK_LT); + ::std::vector<::std::string> hrls; + do { + GET_CHECK_TOK(tok, lex, TOK_LIFETIME); + hrls.push_back( mv$(tok.str()) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_GT); + if( LOOK_AHEAD(lex) == TOK_RWORD_FN || LOOK_AHEAD(lex) == TOK_RWORD_EXTERN ) { + // TODO: Handle HRLS in fn types + return Parse_Type_Fn(lex); + } + else { + return Parse_Type_Path(lex, hrls); + } + } // <ident> - Either a primitive, or a path case TOK_IDENT: // or a primitive @@ -65,33 +84,17 @@ TypeRef Parse_Type_Int(TokenStream& lex) { return TypeRef(TypeRef::TagPath(), AST::Path("", { AST::PathNode("#",{}), AST::PathNode("str",{}) })); } + lex.putback(tok); + return Parse_Type_Path(lex, {}); // - Fall through to path handling // '::' - Absolute path - case TOK_DOUBLE_COLON: { + case TOK_DOUBLE_COLON: lex.putback(tok); - ::std::vector<AST::Path> traits; - ::std::vector< ::std::string> lifetimes; - do { - if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { - GET_TOK(tok, lex); - lifetimes.push_back( tok.str() ); - } - else - traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); - } while( GET_TOK(tok, lex) == TOK_PLUS ); - lex.putback(tok); - if( traits.size() > 1 || lifetimes.size() > 0 ) { - if( lifetimes.size() ) - DEBUG("TODO: Lifetime bounds on trait objects"); - return TypeRef(::std::move(traits)); - } - else - return TypeRef(TypeRef::TagPath(), traits.at(0)); - } + return Parse_Type_Path(lex, {}); // 'super' - Parent relative path case TOK_RWORD_SUPER: - GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); - return TypeRef(TypeRef::TagPath(), AST::Path(AST::Path::TagSuper(), Parse_PathNodes(lex, PATH_GENERIC_TYPE))); + lex.putback(tok); + return Parse_Type_Path(lex, {}); // HACK! Convert && into & & case TOK_DOUBLE_AMP: @@ -206,9 +209,13 @@ TypeRef Parse_Type_Fn(TokenStream& lex) } if( tok.type() == TOK_RWORD_EXTERN ) { - GET_CHECK_TOK(tok, lex, TOK_STRING); - abi = tok.str(); - GET_TOK(tok, lex); + if( GET_TOK(tok, lex) == TOK_STRING ) { + abi = tok.str(); + GET_TOK(tok, lex); + } + else { + abi = "C"; + } } CHECK_TOK(tok, TOK_RWORD_FN); @@ -236,3 +243,28 @@ TypeRef Parse_Type_Fn(TokenStream& lex) return TypeRef(TypeRef::TagFunction(), ::std::move(abi), ::std::move(args), ::std::move(ret_type)); } +TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls) +{ + Token tok; + + ::std::vector<AST::Path> traits; + ::std::vector< ::std::string> lifetimes; + do { + if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { + GET_TOK(tok, lex); + lifetimes.push_back( tok.str() ); + } + else + traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); + } while( GET_TOK(tok, lex) == TOK_PLUS ); + lex.putback(tok); + if( hrls.size() > 0 || traits.size() > 1 || lifetimes.size() > 0 ) { + if( lifetimes.size() ) + DEBUG("TODO: Lifetime bounds on trait objects"); + return TypeRef(mv$(hrls), ::std::move(traits)); + } + else { + return TypeRef(TypeRef::TagPath(), traits.at(0)); + } +} + diff --git a/src/types.hpp b/src/types.hpp index 7484d522..0cb8ba9a 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -90,6 +90,7 @@ TAGGED_UNION(TypeData, None, AST::Path path;
)),
(TraitObject, (
+ ::std::vector<::std::string> hrls;
::std::vector<AST::Path> traits;
))
);
@@ -200,8 +201,8 @@ public: TypeRef(TagPath(), ::std::move(path))
{}
- TypeRef( ::std::vector<AST::Path> traits ):
- m_data(TypeData::make_TraitObject({ ::std::move(traits) }))
+ TypeRef( ::std::vector<::std::string> hrls, ::std::vector<AST::Path> traits ):
+ m_data(TypeData::make_TraitObject({ mv$(hrls), ::std::move(traits) }))
{}
|