From 450d55d26e0265858f60f5a118aac72cf392495f Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Thu, 22 Jan 2015 18:54:56 +0800 Subject: Corrected pattern handling (a bit) --- src/parse/expr.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++--------- src/parse/lex.cpp | 1 + src/parse/lex.hpp | 1 + 3 files changed, 83 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index d9d42460..e91a8b26 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -28,6 +28,8 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) return AST::Expr(Parse_ExprBlockNode(lex)); } +::std::vector Parse_PatternList(TokenStream& lex); + /// Parse a pattern /// /// Examples: @@ -44,36 +46,86 @@ AST::Pattern Parse_Pattern(TokenStream& lex) AST::Path path; Token tok; tok = lex.getToken(); - // 1. Bind mutability + + bool expect_bind = false; + bool is_mut = false; + bool is_ref = false; + // 1. Mutablity + Reference + if( tok.type() == TOK_RWORD_REF ) + { + throw ParseError::Todo("ref bindings"); + is_ref = true; + expect_bind = true; + tok = lex.getToken(); + } if( tok.type() == TOK_RWORD_MUT ) { throw ParseError::Todo("mut bindings"); + is_mut = true; + expect_bind = true; tok = lex.getToken(); } - if( tok.type() == TOK_RWORD_REF ) + + ::std::string bind_name; + if( expect_bind ) { - throw ParseError::Todo("ref bindings"); - tok = lex.getToken(); + CHECK_TOK(tok, TOK_IDENT); + bind_name = tok.str(); + if( GET_TOK(tok, lex) != TOK_AT ) + { + lex.putback(tok); + return AST::Pattern(AST::Pattern::TagBind(), bind_name); + } } - switch( tok.type() ) + + // TODO: If the next token is an ident, parse as a path + if( !expect_bind && tok.type() == TOK_IDENT ) { - case TOK_IDENT: - // 1. Identifiers could be either a bind or a value - // - If the path resolves to a single node, either a local enum value, or a binding lex.putback(tok); path = Parse_Path(lex, false, PATH_GENERIC_EXPR); + // - If the path is trivial if( path.size() == 1 && path[0].args().size() == 0 ) { - // Could be a name binding, check the next token - GET_TOK(tok, lex); - if(tok.type() != TOK_PAREN_OPEN) { + switch( GET_TOK(tok, lex) ) + { + // - If the next token after that is '@', use as bind name and expect an actual pattern + case TOK_AT: + bind_name = path[0].name(); + GET_TOK(tok, 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)); + // - Else, treat as a MaybeBind + default: lex.putback(tok); return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name()); } - lex.putback(tok); } - // otherwise, it's a value check - if(0) + 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()); + } + } + } + + + switch( tok.type() ) + { + case TOK_IDENT: + lex.putback(tok); + path = Parse_Path(lex, false, PATH_GENERIC_EXPR); + if( 0 ) case TOK_DOUBLE_COLON: // 2. Paths are enum/struct names { @@ -97,12 +149,26 @@ AST::Pattern Parse_Pattern(TokenStream& lex) break; 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"); default: throw ParseError::Unexpected(tok); } - throw ParseError::BugCheck("Parse_TT_Stmt should early return"); + throw ParseError::BugCheck("Parse_Pattern should early return"); +} + +::std::vector Parse_PatternList(TokenStream& lex) +{ + Token tok; + ::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 child_pats; } ExprNodeP Parse_ExprBlockNode(TokenStream& lex) diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 9655df0a..7dd8eb3c 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -458,6 +458,7 @@ const char* Token::typestr(enum eTokenType type) case TOK_INTEGER: return "TOK_INTEGER"; case TOK_CHAR: return "TOK_CHAR"; case TOK_FLOAT: return "TOK_FLOAT"; + case TOK_STRING: return "TOK_STRING"; case TOK_CATTR_OPEN: return "TOK_CATTR_OPEN"; case TOK_ATTR_OPEN: return "TOK_ATTR_OPEN"; diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index 6a798909..710f3a6c 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -20,6 +20,7 @@ enum eTokenType TOK_INTEGER, TOK_CHAR, TOK_FLOAT, + TOK_STRING, TOK_CATTR_OPEN, TOK_ATTR_OPEN, -- cgit v1.2.3