From fcec09900f158aa939eb1c96607aaabf4c8171ef Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 7 Mar 2015 12:07:43 +0800 Subject: Added file+line reporting to error messages --- src/macros.cpp | 8 +- src/macros.hpp | 4 +- src/parse/common.hpp | 4 +- src/parse/expr.cpp | 6 +- src/parse/lex.cpp | 14 +- src/parse/lex.hpp | 413 ++++++++++++++++++++++++----------------------- src/parse/parseerror.cpp | 9 +- src/parse/parseerror.hpp | 4 +- src/parse/preproc.cpp | 16 +- src/parse/preproc.hpp | 5 +- src/parse/root.cpp | 121 +++++++++++--- src/parse/tokentree.hpp | 4 +- 12 files changed, 371 insertions(+), 237 deletions(-) (limited to 'src') diff --git a/src/macros.cpp b/src/macros.cpp index fa9ca9ef..7d0c7096 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -68,7 +68,7 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) // Create token stream for input tree TTStream lex(input); if(GET_TOK(tok, lex) == TOK_EOF) { - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } ::std::map bound_tts; // Parse according to rules @@ -102,7 +102,7 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) } // TODO: Actually check if the final token is the closer to the first if( !fail && GET_TOK(tok, lex) == TOK_EOF) { - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } if( !fail && lex.getToken().type() == TOK_EOF ) { @@ -115,6 +115,10 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) throw ParseError::Generic( ::std::string("Macro '") + name + "' was not found" ); } +Position MacroExpander::getPosition() const +{ + return Position("Macro", 0); +} Token MacroExpander::realGetToken() { if( m_ttstream.get() ) diff --git a/src/macros.hpp b/src/macros.hpp index f5779d4d..b2aeda53 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -87,7 +87,9 @@ public: m_ofs(0) { } - virtual Token realGetToken(); + + virtual Position getPosition() const override; + virtual Token realGetToken() override; }; extern MacroExpander Macro_Invoke(const char* name, TokenTree input); diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 0d6d550b..950a204d 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -5,11 +5,11 @@ #define GET_TOK(tok, lex) ((tok = lex.getToken()).type()) #define GET_CHECK_TOK(tok, lex, exp) do {\ if((tok = lex.getToken()).type() != exp) \ - throw ParseError::Unexpected(tok, Token(exp));\ + throw ParseError::Unexpected(lex, tok, Token(exp));\ } while(0) #define CHECK_TOK(tok, exp) do {\ if(tok.type() != exp) \ - throw ParseError::Unexpected(tok, Token(exp));\ + throw ParseError::Unexpected(lex, tok, Token(exp));\ } while(0) enum eParsePathGenericMode diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 2ed992ce..1ee3a2e2 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -155,7 +155,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex) // This may also have to handle range expressions? (and other complexities) throw ParseError::Todo("tuple patterns"); default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } throw ParseError::BugCheck("Parse_Pattern should early return"); } @@ -618,7 +618,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return Parse_Expr0(expanded_macro); } default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } } @@ -701,7 +701,7 @@ TokenTree Parse_TT_Val(TokenStream& lex) break; default: // Oh, fail :( - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } return TokenTree(ret); } diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 2d6873d0..43fc12aa 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -205,6 +205,8 @@ Token Lexer::getToken() { char ch = this->getc(); + if( ch == '\n' ) + return Token(TOK_NEWLINE); if( isspace(ch) ) { while( isspace(this->getc()) ) @@ -311,6 +313,7 @@ Token Lexer::getToken() str.push_back(ch); ch = this->getc(); } + this->putback(); return Token(TOK_COMMENT, str); } case BLOCKCOMMENT: { ::std::string str; @@ -449,6 +452,7 @@ const char* Token::typestr(enum eTokenType type) case TOK_NULL: return "TOK_NULL"; case TOK_EOF: return "TOK_EOF"; + case TOK_NEWLINE: return "TOK_NEWLINE"; case TOK_WHITESPACE: return "TOK_WHITESPACE"; case TOK_COMMENT: return "TOK_COMMENT"; @@ -579,11 +583,15 @@ const char* Token::typestr(enum eTokenType type) return ">>BUGCHECK: BADTOK<<"; } -::std::ostream& operator<<(::std::ostream& os, Token& tok) +::std::ostream& operator<<(::std::ostream& os, const Token& tok) { os << Token::typestr(tok.type()) << "\"" << tok.str() << "\""; return os; } +::std::ostream& operator<<(::std::ostream& os, const Position& p) +{ + return os << p.filename << ":" << p.line; +} TTStream::TTStream(const TokenTree& input_tt): m_input_tt(input_tt) @@ -623,6 +631,10 @@ Token TTStream::realGetToken() } return Token(TOK_EOF); } +Position TTStream::getPosition() const +{ + return Position("TTStream", 0); +} TokenStream::TokenStream(): m_cache_valid(false) diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index 710f3a6c..38f730c5 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -1,201 +1,216 @@ -#ifndef LEX_HPP_INCLUDED -#define LEX_HPP_INCLUDED - -#include "../types.hpp" +#ifndef LEX_HPP_INCLUDED +#define LEX_HPP_INCLUDED + +#include "../types.hpp" #include -#include - -enum eTokenType -{ - TOK_NULL, - TOK_EOF, - - TOK_WHITESPACE, - TOK_COMMENT, - - // Value tokens - TOK_IDENT, - TOK_MACRO, - TOK_LIFETIME, - TOK_INTEGER, - TOK_CHAR, - TOK_FLOAT, +#include + +enum eTokenType +{ + TOK_NULL, + TOK_EOF, + + TOK_NEWLINE, + TOK_WHITESPACE, + TOK_COMMENT, + + // Value tokens + TOK_IDENT, + TOK_MACRO, + TOK_LIFETIME, + TOK_INTEGER, + TOK_CHAR, + TOK_FLOAT, TOK_STRING, - - TOK_CATTR_OPEN, - TOK_ATTR_OPEN, - - // Symbols - TOK_PAREN_OPEN, TOK_PAREN_CLOSE, - TOK_BRACE_OPEN, TOK_BRACE_CLOSE, - TOK_LT, TOK_GT, - TOK_SQUARE_OPEN,TOK_SQUARE_CLOSE, - TOK_COMMA, - TOK_SEMICOLON, - TOK_COLON, - TOK_DOUBLE_COLON, - TOK_STAR, TOK_AMP, - TOK_PIPE, - - TOK_FATARROW, // => - TOK_THINARROW, // -> - - TOK_PLUS, TOK_DASH, - TOK_EXCLAM, - TOK_PERCENT, - TOK_SLASH, - - TOK_DOT, - TOK_DOUBLE_DOT, - TOK_TRIPLE_DOT, - - TOK_EQUAL, - TOK_PLUS_EQUAL, - TOK_DASH_EQUAL, - TOK_PERCENT_EQUAL, - TOK_SLASH_EQUAL, - TOK_STAR_EQUAL, - TOK_AMP_EQUAL, - TOK_PIPE_EQUAL, - - TOK_DOUBLE_EQUAL, - TOK_EXCLAM_EQUAL, - TOK_GTE, - TOK_LTE, - - TOK_DOUBLE_AMP, - TOK_DOUBLE_PIPE, - TOK_DOUBLE_LT, - TOK_DOUBLE_GT, - - TOK_QMARK, - TOK_AT, - TOK_TILDE, - TOK_BACKSLASH, - TOK_CARET, - TOK_BACKTICK, - - // Reserved Words - TOK_RWORD_PUB, - TOK_RWORD_PRIV, - TOK_RWORD_MUT, - TOK_RWORD_CONST, - TOK_RWORD_STATIC, - TOK_RWORD_UNSAFE, - TOK_RWORD_EXTERN, - - TOK_RWORD_CRATE, - TOK_RWORD_MOD, - TOK_RWORD_STRUCT, - TOK_RWORD_ENUM, - TOK_RWORD_TRAIT, - TOK_RWORD_FN, - TOK_RWORD_USE, - TOK_RWORD_IMPL, - TOK_RWORD_TYPE, - - TOK_RWORD_WHERE, - TOK_RWORD_AS, - - TOK_RWORD_LET, - TOK_RWORD_MATCH, - TOK_RWORD_IF, - TOK_RWORD_ELSE, - TOK_RWORD_LOOP, - TOK_RWORD_WHILE, - TOK_RWORD_FOR, - TOK_RWORD_IN, - TOK_RWORD_DO, - - TOK_RWORD_CONTINUE, - TOK_RWORD_BREAK, - TOK_RWORD_RETURN, - TOK_RWORD_YIELD, - TOK_RWORD_BOX, - TOK_RWORD_REF, - - TOK_RWORD_FALSE, - TOK_RWORD_TRUE, - TOK_RWORD_SELF, - TOK_RWORD_SUPER, - - TOK_RWORD_PROC, - TOK_RWORD_MOVE, - TOK_RWORD_ONCE, - - TOK_RWORD_ABSTRACT, - TOK_RWORD_FINAL, - TOK_RWORD_PURE, - TOK_RWORD_OVERRIDE, - TOK_RWORD_VIRTUAL, - - TOK_RWORD_ALIGNOF, - TOK_RWORD_OFFSETOF, - TOK_RWORD_SIZEOF, - TOK_RWORD_TYPEOF, - - TOK_RWORD_BE, - TOK_RWORD_UNSIZED, -}; - -class Token -{ - enum eTokenType m_type; - ::std::string m_str; - enum eCoreType m_datatype; - union { - uint64_t m_intval; - double m_floatval; - }; -public: - Token(); - Token(enum eTokenType type); - Token(enum eTokenType type, ::std::string str); - Token(uint64_t val, enum eCoreType datatype); - Token(double val, enum eCoreType datatype); - - enum eTokenType type() const { return m_type; } - const ::std::string& str() const { return m_str; } - enum eCoreType datatype() const { return m_datatype; } - uint64_t intval() const { return m_intval; } - double floatval() const { return m_floatval; } - - static const char* typestr(enum eTokenType type); -}; - -extern ::std::ostream& operator<<(::std::ostream& os, Token& tok); - -class TokenStream -{ - bool m_cache_valid; - Token m_cache; -public: - TokenStream(); - virtual ~TokenStream(); - Token getToken(); - void putback(Token tok); -protected: - virtual Token realGetToken() = 0; -}; - -class Lexer -{ - ::std::ifstream m_istream; - bool m_last_char_valid; - char m_last_char; -public: - Lexer(::std::string filename); - - Token getToken(); - -private: - signed int getSymbol(); - uint32_t parseEscape(char enclosing); - - char getc(); - void putback(); - - class EndOfFile {}; -}; - -#endif // LEX_HPP_INCLUDED + + TOK_CATTR_OPEN, + TOK_ATTR_OPEN, + + // Symbols + TOK_PAREN_OPEN, TOK_PAREN_CLOSE, + TOK_BRACE_OPEN, TOK_BRACE_CLOSE, + TOK_LT, TOK_GT, + TOK_SQUARE_OPEN,TOK_SQUARE_CLOSE, + TOK_COMMA, + TOK_SEMICOLON, + TOK_COLON, + TOK_DOUBLE_COLON, + TOK_STAR, TOK_AMP, + TOK_PIPE, + + TOK_FATARROW, // => + TOK_THINARROW, // -> + + TOK_PLUS, TOK_DASH, + TOK_EXCLAM, + TOK_PERCENT, + TOK_SLASH, + + TOK_DOT, + TOK_DOUBLE_DOT, + TOK_TRIPLE_DOT, + + TOK_EQUAL, + TOK_PLUS_EQUAL, + TOK_DASH_EQUAL, + TOK_PERCENT_EQUAL, + TOK_SLASH_EQUAL, + TOK_STAR_EQUAL, + TOK_AMP_EQUAL, + TOK_PIPE_EQUAL, + + TOK_DOUBLE_EQUAL, + TOK_EXCLAM_EQUAL, + TOK_GTE, + TOK_LTE, + + TOK_DOUBLE_AMP, + TOK_DOUBLE_PIPE, + TOK_DOUBLE_LT, + TOK_DOUBLE_GT, + + TOK_QMARK, + TOK_AT, + TOK_TILDE, + TOK_BACKSLASH, + TOK_CARET, + TOK_BACKTICK, + + // Reserved Words + TOK_RWORD_PUB, + TOK_RWORD_PRIV, + TOK_RWORD_MUT, + TOK_RWORD_CONST, + TOK_RWORD_STATIC, + TOK_RWORD_UNSAFE, + TOK_RWORD_EXTERN, + + TOK_RWORD_CRATE, + TOK_RWORD_MOD, + TOK_RWORD_STRUCT, + TOK_RWORD_ENUM, + TOK_RWORD_TRAIT, + TOK_RWORD_FN, + TOK_RWORD_USE, + TOK_RWORD_IMPL, + TOK_RWORD_TYPE, + + TOK_RWORD_WHERE, + TOK_RWORD_AS, + + TOK_RWORD_LET, + TOK_RWORD_MATCH, + TOK_RWORD_IF, + TOK_RWORD_ELSE, + TOK_RWORD_LOOP, + TOK_RWORD_WHILE, + TOK_RWORD_FOR, + TOK_RWORD_IN, + TOK_RWORD_DO, + + TOK_RWORD_CONTINUE, + TOK_RWORD_BREAK, + TOK_RWORD_RETURN, + TOK_RWORD_YIELD, + TOK_RWORD_BOX, + TOK_RWORD_REF, + + TOK_RWORD_FALSE, + TOK_RWORD_TRUE, + TOK_RWORD_SELF, + TOK_RWORD_SUPER, + + TOK_RWORD_PROC, + TOK_RWORD_MOVE, + TOK_RWORD_ONCE, + + TOK_RWORD_ABSTRACT, + TOK_RWORD_FINAL, + TOK_RWORD_PURE, + TOK_RWORD_OVERRIDE, + TOK_RWORD_VIRTUAL, + + TOK_RWORD_ALIGNOF, + TOK_RWORD_OFFSETOF, + TOK_RWORD_SIZEOF, + TOK_RWORD_TYPEOF, + + TOK_RWORD_BE, + TOK_RWORD_UNSIZED, +}; + +class Token +{ + enum eTokenType m_type; + ::std::string m_str; + enum eCoreType m_datatype; + union { + uint64_t m_intval; + double m_floatval; + }; +public: + Token(); + Token(enum eTokenType type); + Token(enum eTokenType type, ::std::string str); + Token(uint64_t val, enum eCoreType datatype); + Token(double val, enum eCoreType datatype); + + enum eTokenType type() const { return m_type; } + const ::std::string& str() const { return m_str; } + enum eCoreType datatype() const { return m_datatype; } + uint64_t intval() const { return m_intval; } + double floatval() const { return m_floatval; } + + static const char* typestr(enum eTokenType type); +}; + +extern ::std::ostream& operator<<(::std::ostream& os, const Token& tok); + +struct Position +{ + ::std::string filename; + unsigned int line; + + Position(::std::string filename, unsigned int line): + filename(filename), + line(line) + { + } +}; +extern ::std::ostream& operator<<(::std::ostream& os, const Position& p); + +class TokenStream +{ + bool m_cache_valid; + Token m_cache; +public: + TokenStream(); + virtual ~TokenStream(); + Token getToken(); + void putback(Token tok); + virtual Position getPosition() const = 0; +protected: + virtual Token realGetToken() = 0; +}; + +class Lexer +{ + ::std::ifstream m_istream; + bool m_last_char_valid; + char m_last_char; +public: + Lexer(::std::string filename); + + Token getToken(); + +private: + signed int getSymbol(); + uint32_t parseEscape(char enclosing); + + char getc(); + void putback(); + + class EndOfFile {}; +}; + +#endif // LEX_HPP_INCLUDED diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp index 37beb863..ed7a845c 100644 --- a/src/parse/parseerror.cpp +++ b/src/parse/parseerror.cpp @@ -37,14 +37,15 @@ ParseError::BadChar::~BadChar() throw() { } -ParseError::Unexpected::Unexpected(Token tok): +ParseError::Unexpected::Unexpected(const TokenStream& lex, Token tok): m_tok(tok) { - ::std::cout << "Unexpected(" << tok << ")" << ::std::endl; + ::std::cout << lex.getPosition() << ": Unexpected(" << tok << ")" << ::std::endl; } -ParseError::Unexpected::Unexpected(Token tok, Token exp) +ParseError::Unexpected::Unexpected(const TokenStream& lex, Token tok, Token exp): + m_tok(tok) { - ::std::cout << "Unexpected(" << tok << ", " << exp << ")" << ::std::endl; + ::std::cout << lex.getPosition() << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl; } ParseError::Unexpected::~Unexpected() throw() { diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp index 11324476..33c02a92 100644 --- a/src/parse/parseerror.hpp +++ b/src/parse/parseerror.hpp @@ -56,8 +56,8 @@ class Unexpected: { Token m_tok; public: - Unexpected(Token tok); - Unexpected(Token tok, Token exp); + Unexpected(const TokenStream& lex, Token tok); + Unexpected(const TokenStream& lex, Token tok, Token exp); virtual ~Unexpected() throw (); }; diff --git a/src/parse/preproc.cpp b/src/parse/preproc.cpp index 3e2865b2..c8f0aeea 100644 --- a/src/parse/preproc.cpp +++ b/src/parse/preproc.cpp @@ -1,7 +1,10 @@ #include "preproc.hpp" #include +#include Preproc::Preproc(::std::string path): + m_path(path), + m_line(1), m_lex(path) { //ctor @@ -20,16 +23,25 @@ Token Preproc::getTokenInt() //::std::cout << "getTokenInt: tok = " << tok << ::std::endl; switch(tok.type()) { - case TOK_WHITESPACE: + case TOK_NEWLINE: + m_line ++; continue; - case TOK_COMMENT: + case TOK_WHITESPACE: continue; + case TOK_COMMENT: { + ::std::string comment = tok.str(); + m_line += ::std::count(comment.begin(), comment.end(), '\n'); + continue; } default: return tok; } } } +Position Preproc::getPosition() const +{ + return Position(m_path, m_line); +} Token Preproc::realGetToken() { return getTokenInt(); diff --git a/src/parse/preproc.hpp b/src/parse/preproc.hpp index bedb3076..08fda12d 100644 --- a/src/parse/preproc.hpp +++ b/src/parse/preproc.hpp @@ -6,13 +6,16 @@ class Preproc: public TokenStream { + ::std::string m_path; + unsigned int m_line; Lexer m_lex; public: Preproc(::std::string path); ~Preproc(); - virtual Token realGetToken(); + virtual Position getPosition() const override; + virtual Token realGetToken() override; private: Token getTokenInt(); }; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2b4126e9..ef04ea2f 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -169,7 +169,7 @@ TypeRef Parse_Type(TokenStream& lex) // Immutable pointer return TypeRef(TypeRef::TagPointer(), false, Parse_Type(lex)); default: - throw ParseError::Unexpected(tok, Token(TOK_RWORD_CONST)); + throw ParseError::Unexpected(lex, tok, Token(TOK_RWORD_CONST)); } throw ParseError::BugCheck("Reached end of Parse_Type:STAR"); case TOK_SQUARE_OPEN: { @@ -205,7 +205,7 @@ TypeRef Parse_Type(TokenStream& lex) case TOK_EXCLAM: throw ParseError::Todo("noreturn type"); default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } throw ParseError::BugCheck("Reached end of Parse_Type"); } @@ -228,7 +228,7 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex) break; default: // Oopsie! - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } ::std::string param_name = tok.str(); ret.add_param( AST::TypeParam( is_lifetime, param_name ) ); @@ -425,8 +425,7 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons { refs.push_back( Parse_Type(lex) ); } - if( tok.type() != TOK_PAREN_CLOSE ) - throw ParseError::Unexpected(tok, Token(TOK_PAREN_CLOSE)); + CHECK_TOK(tok, TOK_PAREN_CLOSE); inner = TypeRef(TypeRef::TagTuple(), refs); } throw ParseError::Todo("tuple struct"); @@ -449,14 +448,13 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons tok = lex.getToken(); if(tok.type() == TOK_BRACE_CLOSE) break; - if(tok.type() != TOK_COMMA) - throw ParseError::Unexpected(tok, Token(TOK_COMMA)); + CHECK_TOK(tok, TOK_COMMA); } mod.add_struct(is_public, name, params, items); } else { - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } } @@ -473,6 +471,25 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector m GET_CHECK_TOK(tok, lex, TOK_GT); tok = lex.getToken(); } + + // Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2" + if(tok.type() == TOK_COLON) + { + do + { + if( GET_TOK(tok, lex) == TOK_LIFETIME ) + { + // Lifetime requirement + throw ParseError::Todo("Trait bounds (lifetime)"); + } + else + { + lex.putback(tok); + params.add_bound( AST::GenericBound("Self", Parse_Type(lex)) ); + } + } while(GET_TOK(tok, lex) == TOK_PLUS); + } + // TODO: Support "for Sized?" if(tok.type() == TOK_RWORD_WHERE) { @@ -662,7 +679,7 @@ AST::Impl Parse_Impl(TokenStream& lex) break; } default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } } @@ -693,7 +710,7 @@ void Parse_Use(Preproc& lex, ::std::function fcn path.append( AST::PathNode(tok.str(), {}) ); break; default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } // TODO: Use from crate root while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ) @@ -723,7 +740,7 @@ void Parse_Use(Preproc& lex, ::std::function fcn // early return - can't have anything else after return; default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } GET_TOK(tok, lex); break; @@ -786,11 +803,11 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st { case TOK_BRACE_CLOSE: if( !nested_module ) - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); return ; case TOK_EOF: if( nested_module ) - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); return ; default: lex.putback(tok); @@ -824,7 +841,36 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st Parse_Use(lex, [&mod,is_public](AST::Path p, std::string s) { mod.add_alias(is_public, p, s); }); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; - + + case TOK_RWORD_EXTERN: + switch( GET_TOK(tok, lex) ) + { + case TOK_STRING: + throw ParseError::Todo("'extern \"C\"'"); + break; + case TOK_RWORD_CRATE: + if( GET_TOK(tok, lex) == TOK_STRING ) + { + ::std::string path = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + + mod.add_ext_crate(path, name); + } + else if( tok.type() == TOK_IDENT ) + { + ::std::string name = tok.str(); + + mod.add_ext_crate(name, name); + } + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + break; + default: + throw ParseError::Unexpected(lex, tok); + } + break; + case TOK_RWORD_CONST: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); @@ -892,10 +938,43 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st switch( GET_TOK(tok, lex) ) { case TOK_BRACE_OPEN: - Parse_ModRoot(lex, crate, submod, ""); + Parse_ModRoot(lex, crate, submod, "-"); break; case TOK_SEMICOLON: - throw ParseError::Todo("sub-modules from other files"); + DEBUG("Mod = " << name << ", curpath = " << path); + if( path.back() != '/' ) + { + throw ParseError::Generic( FMT("Can't load from files outside of mod.rs or crate root") ); + } + else + { + ::std::string newpath_dir = path + name + "/"; + ::std::string newpath_file = path + name + ".rs"; + ::std::ifstream ifs_dir (newpath_dir + "mod.rs"); + ::std::ifstream ifs_file(newpath_file); + if( ifs_dir.is_open() && ifs_file.is_open() ) + { + // Collision + } + else if( ifs_dir.is_open() ) + { + // Load from dir + Preproc sub_lex(newpath_dir + "mod.rs"); + Parse_ModRoot(sub_lex, crate, submod, newpath_dir); + } + else if( ifs_file.is_open() ) + { + // Load from file + Preproc sub_lex(newpath_file); + Parse_ModRoot(sub_lex, crate, submod, newpath_file); + } + else + { + // Can't find file + throw ParseError::Generic( FMT("Can't find file for " << name << " in '" << path << "'") ); + } + } + break; default: throw ParseError::Generic("Expected { or ; after module name"); } @@ -903,7 +982,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st break; } default: - throw ParseError::Unexpected(tok); + throw ParseError::Unexpected(lex, tok); } } } @@ -912,7 +991,11 @@ AST::Crate Parse_Crate(::std::string mainfile) { Token tok; - Preproc lex(mainfile); + Preproc lex(mainfile); + + size_t p = mainfile.find_last_of('/'); + ::std::string mainpath = (p != ::std::string::npos ? ::std::string(mainfile.begin(), mainfile.begin()+p+1) : "./"); + AST::Crate crate; AST::Module& rootmod = crate.root_module(); @@ -948,7 +1031,7 @@ AST::Crate Parse_Crate(::std::string mainfile) // Include the std if the 'no_std' attribute was absent // - First need to load the std macros, then can import the prelude - Parse_ModRoot(lex, crate, rootmod, mainfile); + Parse_ModRoot(lex, crate, rootmod, mainpath); return crate; } diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index b1b353ea..f7094357 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -39,8 +39,10 @@ public: TTStream(const TokenTree& input_tt); ~TTStream(); + virtual Position getPosition() const override; + protected: - virtual Token realGetToken(); + virtual Token realGetToken() override; }; extern TokenTree Parse_TT(TokenStream& lex); -- cgit v1.2.3