From d967bbb657fce4f2bea01ba646ae28463fd27fb7 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 18 Mar 2015 12:09:29 +0800 Subject: Array literals, op-equals parsing, super in path, blocks --- src/ast/expr.cpp | 20 ++++ src/ast/expr.hpp | 30 ++++- src/dump_as_rust.cpp | 18 +++ src/parse/eTokenType.enum.h | 3 + src/parse/expr.cpp | 267 ++++++++++++++++++++++---------------------- src/parse/lex.cpp | 3 + src/parse/root.cpp | 11 +- 7 files changed, 209 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 59fe2162..7e0437db 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -69,6 +69,7 @@ SERIALISE_TYPE(Expr::, "Expr", { else _(ExprNode_Integer) else _(ExprNode_Closure) else _(ExprNode_StructLiteral) + else _(ExprNode_Array) else _(ExprNode_Tuple) else _(ExprNode_NamedValue) else _(ExprNode_Field) @@ -334,6 +335,19 @@ NODE(ExprNode_StructLiteral, { os << "/* todo: sl */"; }) +NODE(ExprNode_Array, { + s.item(m_size); + s.item(m_values); +},{ + os << "["; + if( m_size.get() ) + os << *m_values[0] << "; " << *m_size; + else + for(const auto& a : m_values) + os << *a << ","; + os << "]"; +}) + NODE(ExprNode_Tuple, { s.item(m_values); },{ @@ -612,6 +626,12 @@ NV(ExprNode_StructLiteral, for( auto& val : node.m_values ) visit(val.second); }) +NV(ExprNode_Array, +{ + visit(node.m_size); + for( auto& val : node.m_values ) + visit(val); +}) NV(ExprNode_Tuple, { for( auto& val : node.m_values ) diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index e84e3df6..ddcfbae9 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -162,11 +162,10 @@ struct ExprNode_Assign: { enum Operation { NONE, - ADD, - SUB, - MUL, - DIV, - MOD, + ADD, SUB, + MUL, DIV, MOD, + AND, OR , XOR, + SHR, SHL, } m_op; unique_ptr m_slot; unique_ptr m_value; @@ -422,6 +421,25 @@ struct ExprNode_StructLiteral: NODE_METHODS(); }; +// Array +struct ExprNode_Array: + public ExprNode +{ + unique_ptr m_size; // if non-NULL, it's a sized array + ::std::vector< unique_ptr > m_values; + + ExprNode_Array() {} + ExprNode_Array(::std::vector< unique_ptr > vals): + m_values( ::std::move(vals) ) + {} + ExprNode_Array(unique_ptr val, unique_ptr size): + m_size( ::std::move(size) ) + { + m_values.push_back( ::std::move(val) ); + } + + NODE_METHODS(); +}; // Tuple struct ExprNode_Tuple: public ExprNode @@ -612,6 +630,7 @@ public: NT(ExprNode_String); NT(ExprNode_Closure); NT(ExprNode_StructLiteral); + NT(ExprNode_Array); NT(ExprNode_Tuple); NT(ExprNode_NamedValue); @@ -656,6 +675,7 @@ public: NT(ExprNode_String); NT(ExprNode_Closure); NT(ExprNode_StructLiteral); + NT(ExprNode_Array); NT(ExprNode_Tuple); NT(ExprNode_NamedValue); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index f76f5942..1d3fa300 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -362,6 +362,24 @@ public: m_os << indent() << "}"; dec_indent(); } + virtual void visit(AST::ExprNode_Array& n) override { + m_expr_root = false; + m_os << "["; + if( n.m_size.get() ) + { + AST::NodeVisitor::visit(n.m_values[0]); + m_os << "; "; + AST::NodeVisitor::visit(n.m_size); + } + else { + for( auto& item : n.m_values ) + { + AST::NodeVisitor::visit(item); + m_os << ", "; + } + } + m_os << "]"; + } virtual void visit(AST::ExprNode_Tuple& n) override { m_expr_root = false; m_os << "("; diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h index 4209c94a..69f00f02 100644 --- a/src/parse/eTokenType.enum.h +++ b/src/parse/eTokenType.enum.h @@ -61,6 +61,8 @@ _(TOK_DOUBLE_AMP) _(TOK_DOUBLE_PIPE) _(TOK_DOUBLE_LT) _(TOK_DOUBLE_GT) +_(TOK_DOUBLE_LT_EQUAL) +_(TOK_DOUBLE_GT_EQUAL) _(TOK_DOLLAR) @@ -69,6 +71,7 @@ _(TOK_AT) _(TOK_TILDE) _(TOK_BACKSLASH) _(TOK_CARET) +_(TOK_CARET_EQUAL) _(TOK_BACKTICK) // Reserved Words diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 01ecc2cb..88bb021f 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -14,7 +14,6 @@ using AST::ExprNode; ExprNodeP Parse_ExprBlockNode(TokenStream& lex); ExprNodeP Parse_Stmt(TokenStream& lex); ExprNodeP Parse_Expr0(TokenStream& lex); -ExprNodeP Parse_ExprBlocks(TokenStream& lex); ExprNodeP Parse_IfStmt(TokenStream& lex); ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime); ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime); @@ -378,7 +377,7 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) else { CHECK_TOK(tok, TOK_EQUAL); } - ExprNodeP val = Parse_ExprBlocks(lex); + ExprNodeP val = Parse_Expr0(lex); return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), ::std::move(type), ::std::move(val) ); } @@ -393,6 +392,11 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) return Parse_IfStmt(lex); case TOK_RWORD_MATCH: return Parse_Expr_Match(lex); + case TOK_RWORD_UNSAFE: { + auto rv = Parse_ExprBlockNode(lex); + dynamic_cast(*rv).set_unsafe(); + return rv; + } // Fall through to the statement code default: { @@ -503,108 +507,6 @@ ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime) return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::FOR, ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) ); } - -/// Parses the 'stmt' fragment specifier -/// - Flow control -/// - Expressions -ExprNodeP Parse_Stmt(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - switch(GET_TOK(tok, lex)) - { - case TOK_RWORD_RETURN: { - 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: - { - 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"); - } - ::std::string lifetime; - if( GET_TOK(tok, lex) == TOK_LIFETIME ) - { - lifetime = tok.str(); - GET_TOK(tok, lex); - } - ExprNodeP val; - if( tok.type() != TOK_SEMICOLON && tok.type() != TOK_COMMA && tok.type() != TOK_BRACE_CLOSE ) { - lex.putback(tok); - val = Parse_Expr1(lex); - } - else - lex.putback(tok); - return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) ); - } - default: - lex.putback(tok); - return Parse_Expr0(lex); - } -} - -::std::vector Parse_ParenList(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - ::std::vector rv; - GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); - if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE ) - { - lex.putback(tok); - do { - rv.push_back( Parse_Expr0(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - } - return rv; -} - -// 0: Assign -ExprNodeP Parse_Expr0(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - ExprNodeP rv = Parse_ExprBlocks(lex); - auto op = AST::ExprNode_Assign::NONE; - switch( GET_TOK(tok, lex) ) - { - case TOK_PLUS_EQUAL: - op = AST::ExprNode_Assign::ADD; - if(0) - case TOK_DASH_EQUAL: - 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; - } -} - /// Parse an 'if' statement // Note: TOK_RWORD_IF has already been eaten ExprNodeP Parse_IfStmt(TokenStream& lex) @@ -657,7 +559,7 @@ ExprNodeP Parse_IfStmt(TokenStream& lex) else return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) ); } - +/// "match" block ExprNodeP Parse_Expr_Match(TokenStream& lex) { TRACE_FUNCTION; @@ -703,34 +605,113 @@ ExprNodeP Parse_Expr_Match(TokenStream& lex) return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) ); } -// 0.5: Blocks -ExprNodeP Parse_ExprBlocks(TokenStream& lex) +/// Parses the 'stmt' fragment specifier +/// - Flow control +/// - Expressions +ExprNodeP Parse_Stmt(TokenStream& lex) +{ + TRACE_FUNCTION; + Token tok; + + switch(GET_TOK(tok, lex)) + { + case TOK_RWORD_RETURN: { + 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: + { + 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"); + } + ::std::string lifetime; + if( GET_TOK(tok, lex) == TOK_LIFETIME ) + { + lifetime = tok.str(); + GET_TOK(tok, lex); + } + ExprNodeP val; + if( tok.type() != TOK_SEMICOLON && tok.type() != TOK_COMMA && tok.type() != TOK_BRACE_CLOSE ) { + lex.putback(tok); + val = Parse_Expr1(lex); + } + else + lex.putback(tok); + return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) ); + } + default: + lex.putback(tok); + return Parse_Expr0(lex); + } +} + +::std::vector Parse_ParenList(TokenStream& lex) +{ + TRACE_FUNCTION; + Token tok; + + ::std::vector rv; + GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); + if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE ) + { + lex.putback(tok); + do { + rv.push_back( Parse_Expr0(lex) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + } + return rv; +} + +// 0: Assign +ExprNodeP Parse_Expr0(TokenStream& lex) { TRACE_FUNCTION; Token tok; + + ExprNodeP rv = Parse_Expr1(lex); + auto op = AST::ExprNode_Assign::NONE; switch( GET_TOK(tok, lex) ) { - case TOK_BRACE_OPEN: - lex.putback(tok); - return Parse_ExprBlockNode(lex); - case TOK_RWORD_LOOP: - return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) ); - case TOK_RWORD_WHILE: - return Parse_WhileStmt(lex, ""); - case TOK_RWORD_FOR: - return Parse_ForStmt(lex, ""); - case TOK_RWORD_MATCH: - return Parse_Expr_Match(lex); - case TOK_RWORD_IF: - return Parse_IfStmt(lex); - case TOK_RWORD_UNSAFE: { - auto rv = Parse_ExprBlockNode(lex); - dynamic_cast(*rv).set_unsafe(); - return rv; - } + case TOK_PLUS_EQUAL: + op = AST::ExprNode_Assign::ADD; if(0) + case TOK_DASH_EQUAL: + op = AST::ExprNode_Assign::SUB; if(0) + case TOK_STAR_EQUAL: + op = AST::ExprNode_Assign::MUL; if(0) + case TOK_SLASH_EQUAL: + op = AST::ExprNode_Assign::DIV; if(0) + + case TOK_AMP_EQUAL: + op = AST::ExprNode_Assign::AND; if(0) + case TOK_PIPE_EQUAL: + op = AST::ExprNode_Assign::OR ; if(0) + case TOK_CARET_EQUAL: + op = AST::ExprNode_Assign::XOR; if(0) + + case TOK_DOUBLE_GT_EQUAL: + op = AST::ExprNode_Assign::SHR; if(0) + case TOK_DOUBLE_LT_EQUAL: + op = AST::ExprNode_Assign::SHL; if(0) + + case TOK_EQUAL: + op = AST::ExprNode_Assign::NONE; + return NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr1(lex) ); + default: lex.putback(tok); - return Parse_Expr1(lex); + return rv; } } @@ -765,6 +746,7 @@ bool Parse_IsTokValue(eTokenType tok_type) case TOK_STRING: case TOK_RWORD_TRUE: case TOK_RWORD_FALSE: + case TOK_RWORD_SELF: case TOK_RWORD_BOX: case TOK_PAREN_OPEN: return true; @@ -937,11 +919,9 @@ 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) ); + case TOK_SQUARE_OPEN: + val = NEWNODE( AST::ExprNode_Index, ::std::move(val), Parse_Expr0(lex) ); GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - } break; case TOK_DOT: // Field access / method call @@ -1081,6 +1061,25 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) AST::Path path; switch( GET_TOK(tok, lex) ) { + case TOK_BRACE_OPEN: + lex.putback(tok); + return Parse_ExprBlockNode(lex); + case TOK_RWORD_LOOP: + return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) ); + case TOK_RWORD_WHILE: + return Parse_WhileStmt(lex, ""); + case TOK_RWORD_FOR: + return Parse_ForStmt(lex, ""); + case TOK_RWORD_MATCH: + return Parse_Expr_Match(lex); + case TOK_RWORD_IF: + return Parse_IfStmt(lex); + case TOK_RWORD_UNSAFE: { + auto rv = Parse_ExprBlockNode(lex); + dynamic_cast(*rv).set_unsafe(); + return rv; + } + case TOK_IDENT: // Get path lex.putback(tok); @@ -1150,7 +1149,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE ) { // Empty literal - //return NEWNODE( AST::ExprNode_Array, ::std::vector() ); + return NEWNODE( AST::ExprNode_Array, ::std::vector() ); } else { @@ -1161,7 +1160,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) // Repetiion auto count = Parse_Expr0(lex); GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - //return NEWNODE( AST::ExprNode_Array, ::std::move(first), ::std::move(count); ); + return NEWNODE( AST::ExprNode_Array, ::std::move(first), ::std::move(count) ); } else { @@ -1173,10 +1172,10 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) GET_TOK(tok, lex); } CHECK_TOK(tok, TOK_SQUARE_CLOSE); - //return NEWNODE( AST::ExprNode_Array, ::std::move(items) ); + return NEWNODE( AST::ExprNode_Array, ::std::move(items) ); } } - throw ParseError::Todo(lex, "Array literals"); + throw ParseError::BugCheck(lex, "Array literal fell"); case TOK_MACRO: { TokenTree tt = Parse_TT(lex, true); diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index a2459e14..1e5fb1cf 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -74,6 +74,7 @@ static const struct { TOKENT(";", TOK_SEMICOLON), TOKENT("<", TOK_LT), TOKENT("<<", TOK_DOUBLE_LT), + TOKENT("<<=",TOK_DOUBLE_LT_EQUAL), TOKENT("<=", TOK_LTE), TOKENT("=" , TOK_EQUAL), TOKENT("==", TOK_DOUBLE_EQUAL), @@ -81,6 +82,7 @@ static const struct { TOKENT(">", TOK_GT), TOKENT(">=", TOK_GTE), TOKENT(">>", TOK_DOUBLE_GT), + TOKENT(">>=",TOK_DOUBLE_GT_EQUAL), TOKENT("?", TOK_QMARK), TOKENT("@", TOK_AT), // A-Z :: Elsewhere @@ -88,6 +90,7 @@ static const struct { TOKENT("\\", TOK_BACKSLASH), TOKENT("]", TOK_SQUARE_CLOSE), TOKENT("^", TOK_CARET), + TOKENT("^=", TOK_CARET_EQUAL), TOKENT("`", TOK_BACKTICK), TOKENT("{", TOK_BRACE_OPEN), diff --git a/src/parse/root.cpp b/src/parse/root.cpp index cd197292..acd0e9e9 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -251,6 +251,9 @@ TypeRef Parse_Type(TokenStream& lex) case TOK_DOUBLE_COLON: // Path with generics return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE)); + case TOK_RWORD_SUPER: + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + return TypeRef(TypeRef::TagPath(), Parse_PathFrom(lex, AST::Path(AST::Path::TagSuper()), PATH_GENERIC_TYPE)); // HACK! Convert && into & & case TOK_DOUBLE_AMP: @@ -446,12 +449,12 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params) // Parse a single function argument ::std::pair< AST::Pattern, TypeRef> Parse_Function_Arg(TokenStream& lex, bool expect_named) { - TRACE_FUNCTION; + TRACE_FUNCTION_F("expect_named = " << expect_named); Token tok; AST::Pattern pat; - if( expect_named || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) ) + if( expect_named || LOOK_AHEAD(lex) == TOK_UNDERSCORE || LOOK_AHEAD(lex) == TOK_RWORD_MUT || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) ) { pat = Parse_Pattern(lex); GET_CHECK_TOK(tok, lex, TOK_COLON); @@ -566,7 +569,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt // Argument list do { - args.push_back( Parse_Function_Arg(lex, true) ); + args.push_back( Parse_Function_Arg(lex, !can_be_prototype) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_PAREN_CLOSE); } @@ -599,7 +602,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt lex.putback(tok); } - return AST::Function(params, fcn_class, ret_type, args); + return AST::Function(::std::move(params), fcn_class, ::std::move(ret_type), ::std::move(args)); } AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self) -- cgit v1.2.3