From b082aab8d49e3b5a2e1eeee97fd9330f782b7381 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 8 Mar 2015 23:58:56 +0800 Subject: Cleanup to pattern handling --- src/ast/expr.cpp | 4 ++ src/ast/expr.hpp | 2 + src/ast/pattern.hpp | 9 ++++- src/convert/resolve.cpp | 2 +- src/dump_as_rust.cpp | 2 + src/parse/eTokenType.enum.h | 2 + src/parse/expr.cpp | 99 ++++++++++++++++++++++++--------------------- src/parse/lex.cpp | 1 + src/parse/root.cpp | 2 +- 9 files changed, 75 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 8c239092..e29b3068 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -236,6 +236,8 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { #define _(v) case ExprNode_BinOp::v: s << #v; return _(CMPEQU); _(CMPNEQU); + _(BOOLAND); + _(BOOLOR); _(BITAND); _(BITOR); _(BITXOR); @@ -267,6 +269,8 @@ NODE(ExprNode_BinOp, { { case CMPEQU: os << "=="; break; case CMPNEQU: os << "!="; break; + case BOOLAND: os << "&&"; break; + case BOOLOR: os << "||"; break; case BITAND: os << "&"; break; case BITOR: os << "|"; break; case BITXOR: os << "^"; break; diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 9ae6540e..b9ab5d05 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -320,6 +320,8 @@ struct ExprNode_BinOp: CMPLTE, CMPGT, CMPGTE, + BOOLAND, + BOOLOR, BITAND, BITOR, diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 82db2b7c..deda0b97 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -20,6 +20,7 @@ public: enum BindType { MAYBE_BIND, ANY, + REF, VALUE, TUPLE, TUPLE_STRUCT, @@ -83,6 +84,12 @@ public: m_class(VALUE), m_node( ::std::move(node) ) {} + + struct TagReference {}; + Pattern(TagReference, Pattern sub_pattern): + m_class(REF), + m_sub_patterns( { ::std::move(sub_pattern) } ) + {} struct TagTuple {}; Pattern(TagTuple, ::std::vector sub_patterns): @@ -98,7 +105,7 @@ public: {} // Mutators - void set_bind(::std::string name) { + void set_bind(::std::string name, bool is_ref, bool is_mut) { m_binding = name; } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index cba7d375..9a1033c9 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -354,7 +354,7 @@ void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) { // It's a name binding (desugar to 'name @ _') pat = AST::Pattern(); - pat.set_bind(name); + pat.set_bind(name, false, false); } else { diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 1a7737ba..ae6a6337 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -278,6 +278,8 @@ public: case AST::ExprNode_BinOp::CMPLTE: m_os << "<="; break; case AST::ExprNode_BinOp::CMPGT: m_os << ">"; break; case AST::ExprNode_BinOp::CMPGTE: m_os << ">="; break; + case AST::ExprNode_BinOp::BOOLAND:m_os << "&&"; break; + case AST::ExprNode_BinOp::BOOLOR: m_os << "||"; break; case AST::ExprNode_BinOp::BITAND: m_os << "&"; break; case AST::ExprNode_BinOp::BITOR: m_os << "|"; break; case AST::ExprNode_BinOp::BITXOR: m_os << "^"; break; diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h index d3f294b5..4209c94a 100644 --- a/src/parse/eTokenType.enum.h +++ b/src/parse/eTokenType.enum.h @@ -17,6 +17,8 @@ _(TOK_STRING) _(TOK_CATTR_OPEN) _(TOK_ATTR_OPEN) +_(TOK_UNDERSCORE) + // Symbols _(TOK_PAREN_OPEN) _(TOK_PAREN_CLOSE) _(TOK_BRACE_OPEN) _(TOK_BRACE_CLOSE) diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index c7cceee0..3d812fb8 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -30,6 +30,10 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) ::std::vector Parse_PatternList(TokenStream& lex); +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path); +AST::Pattern Parse_PatternReal(TokenStream& lex); + + /// Parse a pattern /// /// Examples: @@ -73,12 +77,14 @@ AST::Pattern Parse_Pattern(TokenStream& lex) bind_name = tok.str(); if( GET_TOK(tok, lex) != TOK_AT ) { + // No '@', it's a name binding lex.putback(tok); return AST::Pattern(AST::Pattern::TagBind(), bind_name); } + + tok = lex.getToken(); } - // TODO: If the next token is an ident, parse as a path if( !expect_bind && tok.type() == TOK_IDENT ) { lex.putback(tok); @@ -95,9 +101,9 @@ AST::Pattern Parse_Pattern(TokenStream& lex) break; // - Else, if the next token is a '(' or '{', treat as a struct/enum case TOK_BRACE_OPEN: - throw ParseError::Todo("Parse_Pattern - Structure patterns"); case TOK_PAREN_OPEN: - return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex)); + lex.putback(tok); + return Parse_PatternReal_Path(lex, path); // - Else, treat as a MaybeBind default: lex.putback(tok); @@ -106,62 +112,62 @@ AST::Pattern Parse_Pattern(TokenStream& lex) } else { - switch(GET_TOK(tok, lex)) - { - case TOK_BRACE_OPEN: - throw ParseError::Todo("Parse_Pattern - Structure patterns"); - case TOK_PAREN_OPEN: - return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex)); - default: - lex.putback(tok); - return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name()); - } + // non-trivial path, has to be a pattern (not a bind) + return Parse_PatternReal_Path(lex, path); } } + lex.putback(tok); + AST::Pattern pat = Parse_PatternReal(lex); + pat.set_bind(bind_name, is_ref, is_mut); + return pat; +} +AST::Pattern Parse_PatternReal(TokenStream& lex) +{ + Token tok; + AST::Path path; - switch( tok.type() ) + switch( GET_TOK(tok, lex) ) { + case TOK_UNDERSCORE: + return AST::Pattern( ); + case TOK_AMP: + return AST::Pattern( AST::Pattern::TagReference(), Parse_PatternReal(lex) ); case TOK_IDENT: lex.putback(tok); - path = Parse_Path(lex, false, PATH_GENERIC_EXPR); - if( 0 ) + return Parse_PatternReal_Path( lex, Parse_Path(lex, false, PATH_GENERIC_EXPR) ); case TOK_DOUBLE_COLON: // 2. Paths are enum/struct names - { - path = Parse_Path(lex, true, PATH_GENERIC_EXPR); - } - switch( GET_TOK(tok, lex) ) - { - case TOK_PAREN_OPEN: { - // A list of internal patterns - ::std::vector child_pats; - do { - child_pats.push_back( Parse_Pattern(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), ::std::move(child_pats)); - } - default: - lex.putback(tok); - return AST::Pattern(AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_NamedValue, ::std::move(path))); - } - break; + return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR) ); case TOK_INTEGER: return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, tok.intval(), tok.datatype()) ); case TOK_STRING: throw ParseError::Todo("string patterns"); case TOK_PAREN_OPEN: - // This may also have to handle range expressions? (and other complexities) - throw ParseError::Todo("tuple patterns"); + return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex)); + case TOK_SQUARE_OPEN: + throw ParseError::Todo("array patterns"); default: throw ParseError::Unexpected(lex, tok); } - throw ParseError::BugCheck("Parse_Pattern should early return"); +} +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path) +{ + Token tok; + + switch( GET_TOK(tok, lex) ) + { + case TOK_PAREN_OPEN: + return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex)); + default: + lex.putback(tok); + return AST::Pattern(AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_NamedValue, ::std::move(path))); + } } ::std::vector Parse_PatternList(TokenStream& lex) { + TRACE_FUNCTION; Token tok; ::std::vector child_pats; do { @@ -237,18 +243,14 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon) return NEWNODE( AST::ExprNode_Return, Parse_Expr1(lex) ); case TOK_RWORD_LOOP: throw ParseError::Todo("loop"); - break; case TOK_RWORD_FOR: throw ParseError::Todo("for"); - break; case TOK_RWORD_WHILE: throw ParseError::Todo("while"); - break; default: lex.putback(tok); return Parse_Expr0(lex); } - } ::std::vector Parse_ParenList(TokenStream& lex) @@ -351,7 +353,12 @@ ExprNodeP Parse_Expr_Match(TokenStream& lex) ExprNodeP val = Parse_Stmt(lex, opt_semicolon); arms.push_back( ::std::make_pair( ::std::move(pat), ::std::move(val) ) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); + + if( GET_TOK(tok, lex) == TOK_COMMA ) + continue; + lex.putback(tok); + + } while( 1 ); CHECK_TOK(tok, TOK_BRACE_CLOSE); return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) ); @@ -405,12 +412,14 @@ ExprNodeP cur(TokenStream& lex) \ // 1: Bool OR LEFTASSOC(Parse_Expr1, Parse_Expr2, case TOK_DOUBLE_PIPE: - throw ParseError::Todo("expr - boolean OR"); + rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLOR, ::std::move(rv), next(lex)); + break; ) // 2: Bool AND LEFTASSOC(Parse_Expr2, Parse_Expr3, case TOK_DOUBLE_AMP: - throw ParseError::Todo("expr - boolean AND"); + rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLAND, ::std::move(rv), next(lex)); + break; ) // 3: (In)Equality LEFTASSOC(Parse_Expr3, Parse_Expr4, diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index a81086ce..678da4d0 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -100,6 +100,7 @@ static const struct { const char* chars; signed int type; } RWORDS[] = { + TOKENT("_", TOK_UNDERSCORE), TOKENT("abstract",TOK_RWORD_ABSTRACT), TOKENT("alignof", TOK_RWORD_ALIGNOF), TOKENT("as", TOK_RWORD_AS), diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 7484609b..f5f48132 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -319,7 +319,6 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) // By-value method fcn_class = AST::Function::CLASS_VALMETHOD; GET_TOK(tok, lex); - throw ParseError::Todo("By-value methods"); } else { @@ -821,6 +820,7 @@ MacroRule Parse_MacroRules_Var(Preproc& lex) auto rep = Parse_TT(lex, true); // - don't care about the enclosing brackets TTStream slex(rep); + // parse token tree into a flattend replacement, handling expansions while(GET_TOK(tok, slex) != TOK_EOF) { if( tok.type() == TOK_DOLLAR ) -- cgit v1.2.3