summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/common.hpp2
-rw-r--r--src/parse/expr.cpp482
-rw-r--r--src/parse/lex.cpp13
-rw-r--r--src/parse/lex.hpp52
-rw-r--r--src/parse/parseerror.cpp15
-rw-r--r--src/parse/parseerror.hpp3
-rw-r--r--src/parse/root.cpp31
-rw-r--r--src/parse/tokentree.hpp7
8 files changed, 380 insertions, 225 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index 3bc599a9..4af48174 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -25,7 +25,9 @@ enum eParsePathGenericMode
};
extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
+extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
extern TypeRef Parse_Type(TokenStream& lex);
+extern void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn);
extern AST::Expr Parse_Expr(TokenStream& lex, bool const_only);
extern AST::Expr Parse_ExprBlock(TokenStream& lex);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index 10b942ac..d0d5bc7f 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -17,6 +17,7 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon);
ExprNodeP Parse_Expr0(TokenStream& lex);
ExprNodeP Parse_ExprBlocks(TokenStream& lex);
ExprNodeP Parse_IfStmt(TokenStream& lex);
+ExprNodeP Parse_Expr_Match(TokenStream& lex);
ExprNodeP Parse_Expr1(TokenStream& lex);
AST::Expr Parse_Expr(TokenStream& lex, bool const_only)
@@ -142,14 +143,21 @@ AST::Pattern Parse_PatternReal(TokenStream& lex)
case TOK_DOUBLE_COLON:
// 2. Paths are enum/struct names
return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR) );
+ case TOK_DASH:
+ GET_CHECK_TOK(tok, lex, TOK_INTEGER);
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, -tok.intval(), tok.datatype()) );
case TOK_INTEGER:
return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, tok.intval(), tok.datatype()) );
+ case TOK_RWORD_TRUE:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, true ) );
+ case TOK_RWORD_FALSE:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, false ) );
case TOK_STRING:
- throw ParseError::Todo("string patterns");
+ 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));
case TOK_SQUARE_OPEN:
- throw ParseError::Todo("array patterns");
+ throw ParseError::Todo(lex, "array patterns");
default:
throw ParseError::Unexpected(lex, tok);
}
@@ -218,8 +226,18 @@ pass_value:
ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)
{
TRACE_FUNCTION;
-
Token tok;
+
+ ::std::string lifetime;
+
+ if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
+ lifetime = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ }
+ else {
+ lex.putback(tok);
+ }
+
// 1. Handle 'let'
// 2. Handle new blocks
// 3. Handle a sequence of expressions broken by ';'
@@ -229,6 +247,14 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)
lex.putback(tok);
opt_semicolon = true;
return Parse_ExprBlockNode(lex);
+ case TOK_RWORD_USE: {
+ opt_semicolon = false;
+ ::std::vector< ::std::pair< ::std::string, AST::Path> > imports;
+ Parse_Use(lex, [&imports](AST::Path p, std::string s) {
+ imports.push_back( ::std::make_pair( ::std::move(s), ::std::move(p) ) );
+ });
+ return NEWNODE( AST::ExprNode_Import, ::std::move(imports) );
+ }
case TOK_RWORD_CONST: {
opt_semicolon = false;
GET_CHECK_TOK(tok, lex, TOK_IDENT);
@@ -253,17 +279,68 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)
ExprNodeP val = Parse_ExprBlocks(lex);
return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), ::std::move(type), ::std::move(val) );
}
- case TOK_RWORD_RETURN:
- return NEWNODE( AST::ExprNode_Return, Parse_Expr1(lex) );
+
+ case TOK_RWORD_RETURN: {
+ if( lifetime.size() )
+ throw ParseError::Unexpected(lex, Token(TOK_LIFETIME, lifetime));
+ ExprNodeP val;
+ if( GET_TOK(tok, lex) != TOK_SEMICOLON ) {
+ lex.putback(tok);
+ val = Parse_Expr1(lex);
+ }
+ else
+ lex.putback(tok);
+ return NEWNODE( AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", ::std::move(val) );
+ }
+ case TOK_RWORD_CONTINUE:
+ case TOK_RWORD_BREAK:
+ {
+ if( lifetime.size() )
+ throw ParseError::Unexpected(lex, Token(TOK_LIFETIME, lifetime));
+ AST::ExprNode_Flow::Type type;
+ switch(tok.type())
+ {
+ case TOK_RWORD_CONTINUE: type = AST::ExprNode_Flow::CONTINUE; break;
+ case TOK_RWORD_BREAK: type = AST::ExprNode_Flow::BREAK; break;
+ default: throw ParseError::BugCheck(/*lex,*/ "continue/break");
+ }
+ if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ {
+ lifetime = tok.str();
+ GET_TOK(tok, lex);
+ }
+ ExprNodeP val;
+ if( tok.type() != TOK_SEMICOLON ) {
+ lex.putback(tok);
+ val = Parse_Expr1(lex);
+ }
+ else
+ lex.putback(tok);
+ return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) );
+ }
+
case TOK_RWORD_LOOP:
- throw ParseError::Todo(lex, "loop");
- case TOK_RWORD_FOR:
- throw ParseError::Todo(lex, "for");
- case TOK_RWORD_WHILE:
- throw ParseError::Todo(lex, "while");
+ opt_semicolon = true;
+ return NEWNODE( AST::ExprNode_Loop, lifetime, Parse_ExprBlockNode(lex) );
+ case TOK_RWORD_WHILE: {
+ opt_semicolon = true;
+ ExprNodeP cnd = Parse_Expr1(lex);
+ return NEWNODE( AST::ExprNode_Loop, lifetime, ::std::move(cnd), Parse_ExprBlockNode(lex) );
+ }
+ case TOK_RWORD_FOR: {
+ opt_semicolon = true;
+ AST::Pattern pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_IN);
+ ExprNodeP val = Parse_Expr1(lex);
+ return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::FOR,
+ ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) );
+ }
case TOK_RWORD_IF:
opt_semicolon = true;
return Parse_IfStmt(lex);
+ case TOK_RWORD_MATCH:
+ opt_semicolon = true;
+ return Parse_Expr_Match(lex);
default:
lex.putback(tok);
return Parse_Expr0(lex);
@@ -295,14 +372,25 @@ ExprNodeP Parse_Expr0(TokenStream& lex)
Token tok;
ExprNodeP rv = Parse_ExprBlocks(lex);
+ auto op = AST::ExprNode_Assign::NONE;
switch( GET_TOK(tok, lex) )
{
- case TOK_EQUAL:
- return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::NONE, ::std::move(rv), Parse_Expr1(lex) );
case TOK_PLUS_EQUAL:
- return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::ADD, ::std::move(rv), Parse_Expr1(lex) );
+ op = AST::ExprNode_Assign::ADD;
+ if(0)
case TOK_DASH_EQUAL:
- return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::SUB, ::std::move(rv), Parse_Expr1(lex) );
+ op = AST::ExprNode_Assign::SUB;
+ if(0)
+ case TOK_SLASH_EQUAL:
+ op = AST::ExprNode_Assign::DIV;
+ if(0)
+ case TOK_STAR_EQUAL:
+ op = AST::ExprNode_Assign::MUL;
+ if(0)
+ case TOK_EQUAL:
+ op = AST::ExprNode_Assign::NONE;
+ return NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_ExprBlocks(lex) );
+
default:
lex.putback(tok);
return rv;
@@ -314,21 +402,24 @@ ExprNodeP Parse_Expr0(TokenStream& lex)
ExprNodeP Parse_IfStmt(TokenStream& lex)
{
TRACE_FUNCTION;
- SET_PARSE_FLAG(lex, disallow_struct_literal);
Token tok;
ExprNodeP cond;
AST::Pattern pat;
bool if_let = false;
- if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
- if_let = true;
- pat = Parse_Pattern(lex);
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- cond = Parse_Expr0(lex);
- }
- else {
- lex.putback(tok);
- cond = Parse_Expr0(lex);
+
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
+ if_let = true;
+ pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ cond = Parse_Expr0(lex);
+ }
+ else {
+ lex.putback(tok);
+ cond = Parse_Expr0(lex);
+ }
}
// Contents
@@ -370,6 +461,7 @@ ExprNodeP Parse_Expr_Match(TokenStream& lex)
SET_PARSE_FLAG(lex, disallow_struct_literal);
switch_val = Parse_Expr1(lex);
}
+ ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) );
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
::std::vector< AST::ExprNode_Match::Arm > arms;
@@ -449,8 +541,59 @@ ExprNodeP cur(TokenStream& lex) \
} \
} \
}
+bool Parse_IsTokValue(eTokenType tok_type)
+{
+ switch( tok_type )
+ {
+ case TOK_DOUBLE_COLON:
+ case TOK_IDENT:
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_STRING:
+ case TOK_RWORD_TRUE:
+ case TOK_RWORD_FALSE:
+ case TOK_RWORD_BOX:
+ case TOK_PAREN_OPEN:
+ return true;
+ default:
+ return false;
+ }
+
+}
+ExprNodeP Parse_Expr1_5(TokenStream& lex);
+// Very evil handling for '..'
+ExprNodeP Parse_Expr1(TokenStream& lex)
+{
+ Token tok;
+ ExprNodeP (*next)(TokenStream&) = Parse_Expr1_5;
+ ExprNodeP left, right;
+
+ if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
+ {
+ lex.putback(tok);
+
+ left = next(lex);
+
+ if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
+ {
+ lex.putback(tok);
+ return ::std::move(left);
+ }
+ }
+ if( Parse_IsTokValue( GET_TOK(tok, lex) ) )
+ {
+ lex.putback(tok);
+ right = next(lex);
+ }
+ else
+ {
+ lex.putback(tok);
+ }
+
+ return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) );
+}
// 1: Bool OR
-LEFTASSOC(Parse_Expr1, Parse_Expr2,
+LEFTASSOC(Parse_Expr1_5, Parse_Expr2,
case TOK_DOUBLE_PIPE:
rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLOR, ::std::move(rv), next(lex));
break;
@@ -536,7 +679,8 @@ LEFTASSOC(Parse_Expr11, Parse_Expr12,
rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::DIVIDE, ::std::move(rv), next(lex));
break;
case TOK_PERCENT:
- throw ParseError::Todo("expr - modulo");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MODULO, ::std::move(rv), next(lex));
+ break;
)
// 12: Unaries
ExprNodeP Parse_ExprFC(TokenStream& lex);
@@ -575,23 +719,32 @@ ExprNodeP Parse_ExprFC(TokenStream& lex)
lex.putback(tok);
val = NEWNODE( AST::ExprNode_CallObject, ::std::move(val), Parse_ParenList(lex) );
break;
+ case TOK_SQUARE_OPEN: {
+ ExprNodeP idx = Parse_Expr0(lex);
+ val = NEWNODE( AST::ExprNode_Index, ::std::move(val), ::std::move(idx) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+ break;
case TOK_DOT:
// Field access / method call
// TODO: What about tuple indexing?
switch(GET_TOK(tok, lex))
{
case TOK_IDENT: {
- ::std::string name = tok.str();
+ AST::PathNode path(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) );
+ val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
break;
case TOK_DOUBLE_COLON:
- throw ParseError::Todo("method calls - generic");
+ GET_CHECK_TOK(tok, lex, TOK_LT);
+ path.args() = Parse_Path_GenericList(lex);
+ val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
+ break;
default:
- val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(name) );
+ val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(path.name()) );
lex.putback(tok);
break;
}
@@ -641,6 +794,42 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
}
+ExprNodeP Parse_ExprVal_Closure(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ ::std::vector< ::std::pair<AST::Pattern, TypeRef> > args;
+
+ while( GET_TOK(tok, lex) != TOK_PIPE )
+ {
+ lex.putback(tok);
+ AST::Pattern pat = Parse_Pattern(lex);
+
+ TypeRef type;
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ type = Parse_Type(lex);
+ else
+ lex.putback(tok);
+
+ args.push_back( ::std::make_pair( ::std::move(pat), ::std::move(type) ) );
+
+ if( GET_TOK(tok, lex) != TOK_COMMA )
+ break;
+ }
+ CHECK_TOK(tok, TOK_PIPE);
+
+ TypeRef rt;
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ rt = Parse_Type(lex);
+ else
+ lex.putback(tok);
+
+ auto code = Parse_Expr0(lex);
+
+ return NEWNODE( AST::ExprNode_Closure, ::std::move(args), ::std::move(rt), ::std::move(code) );
+}
+
ExprNodeP Parse_FormatArgs(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -690,15 +879,23 @@ ExprNodeP Parse_ExprVal(TokenStream& lex)
case TOK_BRACE_OPEN:
if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) )
return Parse_ExprVal_StructLiteral(lex, ::std::move(path));
+ else
+ DEBUG("Not parsing struct literal");
default:
// Value
lex.putback(tok);
return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) );
}
+ case TOK_DOUBLE_PIPE:
+ lex.putback(Token(TOK_PIPE));
+ case TOK_PIPE:
+ return Parse_ExprVal_Closure(lex);
case TOK_INTEGER:
return NEWNODE( AST::ExprNode_Integer, tok.intval(), tok.datatype() );
case TOK_FLOAT:
return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() );
+ case TOK_STRING:
+ return NEWNODE( AST::ExprNode_String, tok.str() );
case TOK_RWORD_TRUE:
return NEWNODE( AST::ExprNode_Bool, true );
case TOK_RWORD_FALSE:
@@ -795,197 +992,82 @@ TokenTree Parse_TT(TokenStream& lex, bool unwrapped)
return TokenTree(items);
}
+/// A wrapping lexer that
+class TTLexer:
+ public TokenStream
+{
+ TokenStream& m_input;
+ Token m_last_token;
+ ::std::vector<TokenTree> m_output;
+public:
+ TTLexer(TokenStream& input):
+ m_input(input)
+ {
+ }
+
+ virtual Position getPosition() const override { return m_input.getPosition(); }
+ virtual Token realGetToken() override {
+ Token tok = m_input.getToken();
+ m_output.push_back( TokenTree(tok) );
+ return tok;
+ }
+
+ TokenTree get_output() {
+ unsigned int eat = (TokenStream::m_cache_valid ? 1 : 0) + TokenStream::m_lookahead.size();
+ DEBUG(eat << " tokens were not consumed");
+ assert( m_output.size() >= eat );
+ assert( m_input.m_lookahead.size() == 0 );
+ assert( m_input.m_cache_valid == false );
+ for( unsigned int i = 0; i < eat; i ++ )
+ {
+ Token tok = m_output[ m_output.size() - eat + i ].tok();
+ DEBUG("Unconsume " << tok);
+ m_input.m_lookahead.push_back( tok );
+ }
+ DEBUG("- output was [" << m_output << "]");
+ m_output.erase( m_output.end() - eat, m_output.end() );
+ DEBUG("Returning [" << m_output << "]");
+ return ::std::move(m_output);
+ }
+};
+
TokenTree Parse_TT_Type(TokenStream& lex)
{
TRACE_FUNCTION;
- Token tok;
+ TTLexer wlex(lex);
- ::std::vector<TokenTree> ret;
- switch(GET_TOK(tok, lex))
- {
- case TOK_AMP:
- throw ParseError::Todo("TokenTree type &-ptr");
- case TOK_STAR:
- throw ParseError::Todo("TokenTree type *-ptr");
- case TOK_DOUBLE_COLON:
- case TOK_IDENT:
- lex.putback(tok);
- return Parse_TT_Path(lex, false);
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- return TokenTree(ret);
+ // discard result
+ Parse_Type(wlex);
+
+ return wlex.get_output();
}
+/// Parse a token tree path
TokenTree Parse_TT_Path(TokenStream& lex, bool mode_expr)
{
TRACE_FUNCTION;
-
+ TTLexer wlex(lex);
Token tok;
- ::std::vector<TokenTree> ret;
- if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ) {
- ret.push_back(TokenTree(tok));
+ if( GET_TOK(tok, wlex) == TOK_DOUBLE_COLON ) {
+ Parse_Path(wlex, true, (mode_expr ? PATH_GENERIC_EXPR : PATH_GENERIC_TYPE));
}
else {
- lex.putback(tok);
+ wlex.putback(tok);
+ Parse_Path(wlex, false, (mode_expr ? PATH_GENERIC_EXPR : PATH_GENERIC_TYPE));
}
- for(;;)
- {
- // Expect an ident
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ret.push_back(TokenTree(tok));
- // If mode is expr, check for a double colon here
- if( mode_expr )
- {
- if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON )
- break;
- ret.push_back( TokenTree(tok) );
- }
-
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- do {
- ret.push_back( TokenTree(tok) );
- ret.push_back(Parse_TT_Type(lex));
- } while(GET_TOK(tok, lex) == TOK_COMMA);
- if( tok.type() != TOK_GT )
- {
- if(tok.type() == TOK_DOUBLE_GT) {
- ret.push_back(TokenTree(Token(TOK_GT)));
- lex.putback(Token(TOK_GT));
- }
- else {
- CHECK_TOK(tok, TOK_GT);
- }
- }
- else {
- ret.push_back(TokenTree(tok));
- }
-
- if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON )
- break;
- ret.push_back(TokenTree(tok));
- }
- else
- {
- lex.putback(tok);
-
- if( !mode_expr )
- {
- if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON )
- break;
- ret.push_back(TokenTree(tok));
- }
- }
- }
- lex.putback(tok);
- return TokenTree(ret);
-}
-/// Parse a token tree path
-TokenTree Parse_TT_Val(TokenStream& lex)
-{
- Token tok;
- ::std::vector<TokenTree> ret;
- switch(GET_TOK(tok, lex))
- {
- case TOK_PAREN_OPEN:
- lex.putback(tok);
- return Parse_TT(lex, false);
-
- case TOK_IDENT:
- case TOK_DOUBLE_COLON: {
- lex.putback(tok);
- TokenTree inner = Parse_TT_Path(lex, true);
- if(GET_TOK(tok, lex) == TOK_BRACE_OPEN) {
- lex.putback(tok);
- ret.push_back(inner);
- ret.push_back(Parse_TT(lex, false));
- }
- else {
- lex.putback(tok);
- return inner;
- }
- break; }
- case TOK_RWORD_SELF:
- case TOK_INTEGER:
- case TOK_FLOAT:
- case TOK_STRING:
- return TokenTree(tok);
- case TOK_RWORD_MATCH:
- ret.push_back(TokenTree(tok));
- ret.push_back(Parse_TT(lex, false));
- break;
- case TOK_RWORD_IF:
- ret.push_back(TokenTree(tok));
- ret.push_back(Parse_TT_Expr(lex));
- if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) {
- ret.push_back(TokenTree(tok));
- ret.push_back(Parse_TT(lex, false));
- }
- else {
- lex.putback(tok);
- }
- break;
- default:
- // Oh, fail :(
- throw ParseError::Unexpected(lex, tok);
- }
- return TokenTree(ret);
+ return wlex.get_output();
}
/// Parse a token tree expression
TokenTree Parse_TT_Expr(TokenStream& lex)
{
TRACE_FUNCTION;
+ TTLexer wlex(lex);
- Token tok;
- ::std::vector<TokenTree> ret;
-
- ret.push_back(Parse_TT_Val(lex));
- // 1. Get left associative blocks until nothing matches
- bool cont = true;
- while(cont)
- {
- switch(GET_TOK(tok, lex))
- {
- case TOK_PLUS:
- case TOK_DASH:
- case TOK_SLASH:
- case TOK_STAR:
- case TOK_PERCENT:
- ret.push_back(tok);
- ret.push_back(Parse_TT_Val(lex));
- break;
- case TOK_PAREN_OPEN:
- lex.putback(tok);
- ret.push_back(Parse_TT(lex, false));
- break;
- case TOK_DOT:
- ret.push_back(tok);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ret.push_back(tok);
- switch(GET_TOK(tok, lex))
- {
- case TOK_DOUBLE_COLON:
- throw ParseError::Todo("Generic type params in TT expr");
- case TOK_PAREN_OPEN:
- lex.putback(tok);
- ret.push_back(Parse_TT(lex, false));
- break;
- default:
- lex.putback(tok);
- break;
- }
- break;
- default:
- lex.putback(tok);
- cont = false;
- break;
- }
- }
- return TokenTree(ret);
-
+ Parse_Expr1(wlex);
+
+ return wlex.get_output();
}
TokenTree Parse_TT_Stmt(TokenStream& lex)
{
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index b290b3f1..d469d46d 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -623,6 +623,7 @@ SERIALISE_TYPE_S(Token, {
TTStream::TTStream(const TokenTree& input_tt):
m_input_tt(input_tt)
{
+ DEBUG("input_tt = [" << input_tt << "]");
m_stack.push_back( ::std::make_pair(0, &input_tt) );
}
TTStream::~TTStream()
@@ -671,6 +672,14 @@ TokenStream::~TokenStream()
{
}
+Token TokenStream::innerGetToken()
+{
+ Token ret = this->realGetToken();
+ if( ret.get_pos().filename.size() == 0 )
+ ret.set_pos( this->getPosition() );
+ //DEBUG("ret.get_pos() = " << ret.get_pos());
+ return ret;
+}
Token TokenStream::getToken()
{
if( m_cache_valid )
@@ -687,7 +696,7 @@ Token TokenStream::getToken()
}
else
{
- Token ret = this->realGetToken();
+ Token ret = this->innerGetToken();
::std::cout << "getToken[" << typeid(*this).name() << "] - " << ret << ::std::endl;
return ret;
}
@@ -723,7 +732,7 @@ eTokenType TokenStream::lookahead(unsigned int i)
while( i >= m_lookahead.size() )
{
DEBUG("lookahead - read #" << m_lookahead.size());
- m_lookahead.push_back( this->realGetToken() );
+ m_lookahead.push_back( this->innerGetToken() );
}
return m_lookahead[i].type();
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index c754c61d..da56c6ba 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -12,6 +12,23 @@ enum eTokenType
#undef _
};
+struct Position
+{
+ ::std::string filename;
+ unsigned int line;
+
+ Position():
+ filename(""),
+ line(0)
+ {}
+ Position(::std::string filename, unsigned int line):
+ filename(filename),
+ line(line)
+ {
+ }
+};
+extern ::std::ostream& operator<<(::std::ostream& os, const Position& p);
+
class Token:
public Serialisable
{
@@ -22,6 +39,7 @@ class Token:
uint64_t m_intval;
double m_floatval;
};
+ Position m_pos;
public:
Token();
Token(const Token& t) = default;
@@ -30,7 +48,8 @@ public:
m_type(t.m_type),
m_str( ::std::move(t.m_str) ),
m_datatype( t.m_datatype ),
- m_intval( t.m_intval )
+ m_intval( t.m_intval ),
+ m_pos( ::std::move(t.m_pos) )
{
t.m_type = TOK_NULL;
}
@@ -45,6 +64,9 @@ public:
uint64_t intval() const { return m_intval; }
double floatval() const { return m_floatval; }
+ void set_pos(Position pos) { m_pos = pos; }
+ const Position& get_pos() const { return m_pos; }
+
static const char* typestr(enum eTokenType type);
static eTokenType typefromstr(const ::std::string& s);
@@ -53,27 +75,23 @@ public:
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);
-
/// State the parser needs to pass down via a second channel.
struct ParseState
{
bool disallow_struct_literal = false;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const ParseState& ps) {
+ os << "ParseState {";
+ if(ps.disallow_struct_literal) os << " disallow_struct_literal";
+ os << " }";
+ return os;
+ }
};
class TokenStream
{
+ friend class TTLexer; // needs access to internals to know what was consumed
+
bool m_cache_valid;
Token m_cache;
::std::vector<Token> m_lookahead;
@@ -90,6 +108,8 @@ public:
protected:
virtual Token realGetToken() = 0;
+private:
+ Token innerGetToken();
};
class SavedParseState
@@ -100,9 +120,11 @@ public:
SavedParseState(TokenStream& lex, ParseState state):
m_lex(lex),
m_state(state)
- {}
+ {
+ }
~SavedParseState()
{
+ DEBUG("Restoring " << m_state);
m_lex.parse_state() = m_state;
}
};
diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp
index e5385257..3905ae33 100644
--- a/src/parse/parseerror.cpp
+++ b/src/parse/parseerror.cpp
@@ -17,6 +17,11 @@ ParseError::Generic::Generic(const TokenStream& lex, ::std::string message)
::std::cout << lex.getPosition() << ": Generic(" << message << ")" << ::std::endl;
}
+ParseError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message):
+ m_message(message)
+{
+ ::std::cout << lex.getPosition() << "BugCheck(" << message << ")" << ::std::endl;
+}
ParseError::BugCheck::BugCheck(::std::string message):
m_message(message)
{
@@ -49,12 +54,18 @@ ParseError::BadChar::~BadChar() throw()
ParseError::Unexpected::Unexpected(const TokenStream& lex, Token tok):
m_tok(tok)
{
- ::std::cout << lex.getPosition() << ": Unexpected(" << tok << ")" << ::std::endl;
+ auto pos = tok.get_pos();
+ if(pos.filename == "")
+ pos = lex.getPosition();
+ ::std::cout << pos << ": Unexpected(" << tok << ")" << ::std::endl;
}
ParseError::Unexpected::Unexpected(const TokenStream& lex, Token tok, Token exp):
m_tok(tok)
{
- ::std::cout << lex.getPosition() << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl;
+ auto pos = tok.get_pos();
+ if(pos.filename == "")
+ pos = lex.getPosition();
+ ::std::cout << pos << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl;
}
ParseError::Unexpected::~Unexpected() throw()
{
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp
index bfea40b3..911312c5 100644
--- a/src/parse/parseerror.hpp
+++ b/src/parse/parseerror.hpp
@@ -29,6 +29,7 @@ class BugCheck:
::std::string m_message;
public:
BugCheck(::std::string message);
+ BugCheck(const TokenStream& lex, ::std::string message);
virtual ~BugCheck() throw () {}
};
@@ -64,6 +65,8 @@ public:
};
+#define ASSERT(lex, cnd) do { if( !(cnd) ) throw ParseError::BugCheck(lex, "Assertion failed: "#cnd); } while(0)
+
}
#endif // PARSEERROR_HPP_INCLUDED
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 5b14ff02..c64dbb17 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -149,9 +149,16 @@ TypeRef Parse_Type(TokenStream& lex)
{
TRACE_FUNCTION;
- Token tok = lex.getToken();
- switch(tok.type())
+ Token tok;
+
+ switch( GET_TOK(tok, lex) )
{
+ case TOK_RWORD_EXTERN:
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ // abi = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ case TOK_RWORD_FN:
+ throw ParseError::Todo(lex, "Function types");
case TOK_LT: {
DEBUG("Associated type");
// <Type as Trait>::Inner
@@ -306,7 +313,7 @@ void Parse_TypeConds(TokenStream& lex, AST::TypeParams& params)
}
/// Parse a function definition (after the 'fn')
-AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
+AST::Function Parse_FunctionDef(TokenStream& lex, AST::MetaItems attrs, bool allow_no_code=false)
{
TRACE_FUNCTION;
@@ -618,7 +625,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
- trait.add_function( ::std::move(name), Parse_FunctionDef(lex, true) );
+ trait.add_function( ::std::move(name), Parse_FunctionDef(lex, item_attrs, true) );
break; }
default:
throw ParseError::Generic("Unexpected token, expected 'type' or 'fn'");
@@ -776,7 +783,7 @@ AST::Impl Parse_Impl(TokenStream& lex)
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
- impl.add_function(is_public, name, Parse_FunctionDef(lex));
+ impl.add_function(is_public, name, Parse_FunctionDef(lex, item_attrs));
break; }
default:
@@ -1255,10 +1262,22 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
mod.add_global(is_public, is_mut, name, type, val);
break; }
+ case TOK_RWORD_UNSAFE:
+ meta_items.push_back( AST::MetaItem("#UNSAFE") );
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, ::std::move(meta_items)));
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ break;
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
- mod.add_function(is_public, name, Parse_FunctionDef(lex));
+ mod.add_function(is_public, name, Parse_FunctionDef(lex, ::std::move(meta_items)));
break; }
case TOK_RWORD_TYPE: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp
index b3156f66..eaaf6623 100644
--- a/src/parse/tokentree.hpp
+++ b/src/parse/tokentree.hpp
@@ -28,6 +28,13 @@ public:
const Token& tok() const {
return m_tok;
}
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TokenTree& tt) {
+ if( tt.m_subtrees.size() == 0 )
+ return os << "TokenTree(" << tt.m_tok << ")";
+ else
+ return os << "TokenTree([" << tt.m_subtrees << "])";
+ }
};
class TTStream: