summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/common.hpp1
-rw-r--r--src/parse/expr.cpp45
-rw-r--r--src/parse/lex.cpp45
-rw-r--r--src/parse/lex.hpp2
-rw-r--r--src/parse/parseerror.cpp4
-rw-r--r--src/parse/parseerror.hpp1
-rw-r--r--src/parse/root.cpp65
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 )