diff options
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/common.hpp | 1 | ||||
-rw-r--r-- | src/parse/expr.cpp | 45 | ||||
-rw-r--r-- | src/parse/lex.cpp | 45 | ||||
-rw-r--r-- | src/parse/lex.hpp | 2 | ||||
-rw-r--r-- | src/parse/parseerror.cpp | 4 | ||||
-rw-r--r-- | src/parse/parseerror.hpp | 1 | ||||
-rw-r--r-- | src/parse/root.cpp | 65 |
7 files changed, 123 insertions, 40 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index ff72920c..3bc599a9 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -3,6 +3,7 @@ #include <iostream>
#define GET_TOK(tok, lex) ((tok = lex.getToken()).type())
+#define LOOK_AHEAD(lex) (lex.lookahead(0))
#define GET_CHECK_TOK(tok, lex, exp) do {\
if((tok = lex.getToken()).type() != exp) { \
DEBUG("GET_CHECK_TOK " << __FILE__ << ":" << __LINE__); \
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 0bebbc64..10b942ac 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -256,11 +256,11 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon) case TOK_RWORD_RETURN:
return NEWNODE( AST::ExprNode_Return, Parse_Expr1(lex) );
case TOK_RWORD_LOOP:
- throw ParseError::Todo("loop");
+ throw ParseError::Todo(lex, "loop");
case TOK_RWORD_FOR:
- throw ParseError::Todo("for");
+ throw ParseError::Todo(lex, "for");
case TOK_RWORD_WHILE:
- throw ParseError::Todo("while");
+ throw ParseError::Todo(lex, "while");
case TOK_RWORD_IF:
opt_semicolon = true;
return Parse_IfStmt(lex);
@@ -575,25 +575,34 @@ ExprNodeP Parse_ExprFC(TokenStream& lex) lex.putback(tok);
val = NEWNODE( AST::ExprNode_CallObject, ::std::move(val), Parse_ParenList(lex) );
break;
- case TOK_DOT: {
+ case TOK_DOT:
// Field access / method call
// TODO: What about tuple indexing?
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
- switch( GET_TOK(tok, lex) )
+ switch(GET_TOK(tok, lex))
{
- case TOK_PAREN_OPEN:
- lex.putback(tok);
- val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), AST::PathNode(name, {}), Parse_ParenList(lex) );
+ case TOK_IDENT: {
+ ::std::string name = tok.str();
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_PAREN_OPEN:
+ lex.putback(tok);
+ val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), AST::PathNode(name, {}), Parse_ParenList(lex) );
+ break;
+ case TOK_DOUBLE_COLON:
+ throw ParseError::Todo("method calls - generic");
+ default:
+ val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(name) );
+ lex.putback(tok);
+ break;
+ }
+ break; }
+ case TOK_INTEGER:
+ val = NEWNODE( AST::ExprNode_Field, ::std::move(val), FMT(tok.intval()) );
break;
- case TOK_DOUBLE_COLON:
- throw ParseError::Todo("method calls - generic");
default:
- val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(name) );
- lex.putback(tok);
- break;
+ throw ParseError::Unexpected(lex, tok);
}
- break; }
+ break;
default:
lex.putback(tok);
return val;
@@ -737,8 +746,8 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) }
else
{
- MacroExpander expanded_macro = Macro_Invoke(name.c_str(), tt);
- return Parse_Expr0(expanded_macro);
+ auto expanded_macro = Macro_Invoke(lex, name, tt);
+ return Parse_Expr0(*expanded_macro);
}
}
default:
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index fc2c7401..b290b3f1 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -76,8 +76,8 @@ static const struct { TOKENT("==", TOK_DOUBLE_EQUAL), TOKENT("=>", TOK_FATARROW), TOKENT(">", TOK_GT), - TOKENT(">>", TOK_DOUBLE_GT), TOKENT(">=", TOK_GTE), + TOKENT(">>", TOK_DOUBLE_GT), TOKENT("?", TOK_QMARK), TOKENT("@", TOK_AT), // A-Z :: Elsewhere @@ -678,6 +678,13 @@ Token TokenStream::getToken() m_cache_valid = false; return m_cache; } + else if( m_lookahead.size() ) + { + Token ret = m_lookahead.front(); + m_lookahead.erase(m_lookahead.begin()); + ::std::cout << "getToken[" << typeid(*this).name() << "] - " << ret << ::std::endl; + return ret; + } else { Token ret = this->realGetToken(); @@ -687,6 +694,38 @@ Token TokenStream::getToken() } void TokenStream::putback(Token tok) { - m_cache_valid = true; - m_cache = tok; + if( m_cache_valid ) + { + DEBUG("" << getPosition()); + throw ParseError::BugCheck("Double putback"); + } + else + { + m_cache_valid = true; + m_cache = tok; + } } + +eTokenType TokenStream::lookahead(unsigned int i) +{ + const unsigned int MAX_LOOKAHEAD = 3; + + if( m_cache_valid ) + { + if( i == 0 ) + return m_cache.type(); + i --; + } + + if( i >= MAX_LOOKAHEAD ) + throw ParseError::BugCheck("Excessive lookahead"); + + while( i >= m_lookahead.size() ) + { + DEBUG("lookahead - read #" << m_lookahead.size()); + m_lookahead.push_back( this->realGetToken() ); + } + + return m_lookahead[i].type(); +} + diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index bea5698a..c754c61d 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -76,12 +76,14 @@ class TokenStream { bool m_cache_valid; Token m_cache; + ::std::vector<Token> m_lookahead; ParseState m_parse_state; public: TokenStream(); virtual ~TokenStream(); Token getToken(); void putback(Token tok); + eTokenType lookahead(unsigned int count); virtual Position getPosition() const = 0; ParseState& parse_state() { return m_parse_state; } diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp index b0674c07..e5385257 100644 --- a/src/parse/parseerror.cpp +++ b/src/parse/parseerror.cpp @@ -12,6 +12,10 @@ ParseError::Generic::Generic(::std::string message): {
::std::cout << "Generic(" << message << ")" << ::std::endl;
}
+ParseError::Generic::Generic(const TokenStream& lex, ::std::string message)
+{
+ ::std::cout << lex.getPosition() << ": Generic(" << message << ")" << ::std::endl;
+}
ParseError::BugCheck::BugCheck(::std::string message):
m_message(message)
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp index 5868f629..bfea40b3 100644 --- a/src/parse/parseerror.hpp +++ b/src/parse/parseerror.hpp @@ -19,6 +19,7 @@ class Generic: ::std::string m_message;
public:
Generic(::std::string message);
+ Generic(const TokenStream& lex, ::std::string message);
virtual ~Generic() throw () {}
};
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index b6b7af15..5b14ff02 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -8,6 +8,7 @@ #include <cassert>
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);
::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
@@ -17,12 +18,22 @@ void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList< ::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) );
@@ -38,6 +49,7 @@ void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList< CHECK_TOK(tok, TOK_GT);
}
+ // TODO: Actually use the lifetimes/assoc_bounds
return types;
}
@@ -477,24 +489,30 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons }
if(tok.type() == TOK_PAREN_OPEN)
{
- TypeRef inner = Parse_Type(lex);
- tok = lex.getToken();
- if(tok.type() != TOK_PAREN_CLOSE)
+ // Tuple structs
+ ::std::vector<AST::StructItem> refs;
+ while(GET_TOK(tok, lex) != TOK_PAREN_CLOSE)
{
- ::std::vector<TypeRef> refs;
- refs.push_back(inner);
- while( (tok = lex.getToken()).type() == TOK_COMMA )
- {
- refs.push_back( Parse_Type(lex) );
- }
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- inner = TypeRef(TypeRef::TagTuple(), refs);
+ bool is_pub = false;
+ if(tok.type() == TOK_RWORD_PUB)
+ is_pub = true;
+ else
+ lex.putback(tok);
+
+ refs.push_back( AST::StructItem( "", Parse_Type(lex), is_pub ) );
+ if( GET_TOK(tok, lex) != TOK_COMMA )
+ break;
}
- throw ParseError::Todo("tuple struct");
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ if( refs.size() == 0 )
+ throw ParseError::Generic(lex, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
+ mod.add_struct(is_public, ::std::move(name), ::std::move(params), ::std::move(refs));
}
else if(tok.type() == TOK_SEMICOLON)
{
- throw ParseError::Todo("unit-like struct");
+ // Unit-like struct
+ mod.add_struct(is_public, name, params, ::std::vector<AST::StructItem>());
}
else if(tok.type() == TOK_BRACE_OPEN)
{
@@ -512,6 +530,8 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons break;
CHECK_TOK(tok, TOK_COMMA);
}
+ if( items.size() == 0 )
+ throw ParseError::Generic(lex, "Use 'struct Name;' instead of 'struct Name { }' ... ning-nong");
mod.add_struct(is_public, name, params, items);
}
else
@@ -567,6 +587,14 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) CHECK_TOK(tok, TOK_BRACE_OPEN);
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+
switch(tok.type())
{
case TOK_RWORD_STATIC: {
@@ -721,9 +749,9 @@ AST::Impl Parse_Impl(TokenStream& lex) AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_type) );
// A sequence of method implementations
- AST::MetaItems item_attrs;
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ AST::MetaItems item_attrs;
while( tok.type() == TOK_ATTR_OPEN )
{
item_attrs.push_back( Parse_MetaItem(lex) );
@@ -774,10 +802,10 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> switch( GET_TOK(tok, lex) )
{
case TOK_RWORD_SELF:
- throw ParseError::Todo("Parse_Use - self");
+ path = AST::Path( ); // relative path
break;
case TOK_RWORD_SUPER:
- throw ParseError::Todo("Parse_Use - super");
+ throw ParseError::Todo(lex, "Parse_Use - super");
break;
case TOK_IDENT:
path.append( AST::PathNode(tok.str(), {}) );
@@ -1138,8 +1166,8 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, }
::std::string name = tok.str();
- MacroExpander expanded_macro = Macro_Invoke(name.c_str(), tt);
- Parse_ModRoot_Items(expanded_macro, crate, mod, modstack, path);
+ auto expanded_macro = Macro_Invoke(lex, name.c_str(), tt);
+ Parse_ModRoot_Items(*expanded_macro, crate, mod, modstack, path);
}
break;
@@ -1349,7 +1377,6 @@ void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList< LList<AST::Module*> modstack(prev_modstack, &mod);
Macro_SetModule(modstack);
- const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;'
Token tok;
if( crate.m_load_std )
|