summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-07 12:07:43 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-07 12:07:43 +0800
commitfcec09900f158aa939eb1c96607aaabf4c8171ef (patch)
treeeaac668a8d19b56fee0cdafb218ec069cdab8bc5 /src
parenta9692e359884672b30e1742bada368330115cc14 (diff)
downloadmrust-fcec09900f158aa939eb1c96607aaabf4c8171ef.tar.gz
Added file+line reporting to error messages
Diffstat (limited to 'src')
-rw-r--r--src/macros.cpp8
-rw-r--r--src/macros.hpp4
-rw-r--r--src/parse/common.hpp4
-rw-r--r--src/parse/expr.cpp6
-rw-r--r--src/parse/lex.cpp14
-rw-r--r--src/parse/lex.hpp413
-rw-r--r--src/parse/parseerror.cpp9
-rw-r--r--src/parse/parseerror.hpp4
-rw-r--r--src/parse/preproc.cpp16
-rw-r--r--src/parse/preproc.hpp5
-rw-r--r--src/parse/root.cpp121
-rw-r--r--src/parse/tokentree.hpp4
12 files changed, 371 insertions, 237 deletions
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<const char*,TokenTree,cmp_str> 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 <string>
-#include <fstream>
-
-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 <fstream>
+
+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 <iostream>
+#include <algorithm>
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<AST::MetaItem> 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<void(AST::Path, ::std::string)> 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<void(AST::Path, ::std::string)> 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);