From 627a71e3bff7ab13e4a472e2c3da7e917782edd9 Mon Sep 17 00:00:00 2001 From: "John Hodge (bugs)" Date: Wed, 3 Dec 2014 23:03:30 +0800 Subject: Hacking in patterns --- ast/ast.cpp | 33 ++++++++++++++++++- ast/ast.hpp | 62 ++++++++++++++++++++++++++++------- parse/common.hpp | 1 + parse/expr.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++----- parse/root.cpp | 11 +++++-- 5 files changed, 183 insertions(+), 22 deletions(-) diff --git a/ast/ast.cpp b/ast/ast.cpp index 4bba2b61..bf86649b 100644 --- a/ast/ast.cpp +++ b/ast/ast.cpp @@ -6,6 +6,29 @@ namespace AST { +Path::Path() +{ +} +Path::Path(Path::TagAbsolute) +{ +} + +const ::std::string& PathNode::name() const +{ + return m_name; +} +const TypeParams& PathNode::args() const +{ + return m_params; +} + +Pattern::Pattern(TagMaybeBind, ::std::string name) +{ +} +Pattern::Pattern(TagValue, ExprNode node) +{ +} + void Module::add_constant(bool is_public, ::std::string name, TypeRef type, Expr val) { ::std::cout << "add_constant()" << ::std::endl; @@ -31,7 +54,15 @@ ExprNode::ExprNode(TagBlock, ::std::vector nodes) } ExprNode::ExprNode(TagInteger, uint64_t value, enum eCoreType datatype) { - +} +ExprNode::ExprNode(TagCallPath, Path path, ::std::vector args) +{ +} +ExprNode::ExprNode(TagMatch, ExprNode val, ::std::vector< ::std::pair > arms) +{ +} +ExprNode::ExprNode(TagNamedValue, Path path) +{ } TypeParam::TypeParam(bool is_lifetime, ::std::string name) diff --git a/ast/ast.hpp b/ast/ast.hpp index c3bc549b..cfdf23e4 100644 --- a/ast/ast.hpp +++ b/ast/ast.hpp @@ -3,16 +3,58 @@ #include #include +#include #include "../coretypes.hpp" class TypeRef; namespace AST { +class ExprNode; + +class TypeParam +{ +public: + TypeParam(bool is_lifetime, ::std::string name); + void addLifetimeBound(::std::string name); + void addTypeBound(TypeRef type); +}; + +typedef ::std::vector TypeParams; +typedef ::std::pair< ::std::string, TypeRef> StructItem; + +class PathNode +{ + ::std::string m_name; + TypeParams m_params; +public: + const ::std::string& name() const; + const TypeParams& args() const; +}; + class Path { public: + Path(); + struct TagAbsolute {}; + Path(TagAbsolute); + void append(::std::string str) {} + size_t length() const {return 0;} + + PathNode& operator[](size_t idx) { throw ::std::out_of_range("Path []"); } +}; + +class Pattern +{ +public: + Pattern(); + + struct TagMaybeBind {}; + Pattern(TagMaybeBind, ::std::string name); + + struct TagValue {}; + Pattern(TagValue, ExprNode node); }; class ExprNode @@ -28,6 +70,15 @@ public: struct TagInteger {}; ExprNode(TagInteger, uint64_t value, enum eCoreType datatype); + + struct TagCallPath {}; + ExprNode(TagCallPath, Path path, ::std::vector args); + + struct TagMatch {}; + ExprNode(TagMatch, ExprNode val, ::std::vector< ::std::pair > arms); + + struct TagNamedValue {}; + ExprNode(TagNamedValue, Path path); }; class Expr @@ -37,17 +88,6 @@ public: Expr(ExprNode node) {} }; -class TypeParam -{ -public: - TypeParam(bool is_lifetime, ::std::string name); - void addLifetimeBound(::std::string name); - void addTypeBound(TypeRef type); -}; - -typedef ::std::vector TypeParams; -typedef ::std::pair< ::std::string, TypeRef> StructItem; - class Module { public: diff --git a/parse/common.hpp b/parse/common.hpp index 34ea65a4..211fadee 100644 --- a/parse/common.hpp +++ b/parse/common.hpp @@ -1,6 +1,7 @@ #ifndef PARSE_COMMON_HPP_INCLUDED #define PARSEERROR_HPP_INCLUDED +#define GET_TOK(tok, lex) ((tok = lex.getToken()).type()) #define GET_CHECK_TOK(tok, lex, exp) do {\ if((tok = lex.getToken()).type() != exp) \ throw ParseError::Unexpected(tok, Token(exp));\ diff --git a/parse/expr.cpp b/parse/expr.cpp index aff1f31d..3c6e2199 100644 --- a/parse/expr.cpp +++ b/parse/expr.cpp @@ -23,6 +23,58 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) return AST::Expr(Parse_ExprBlockNode(lex)); } +AST::Pattern Parse_Pattern(TokenStream& lex) +{ + AST::Path path; + Token tok; + tok = lex.getToken(); + if( tok.type() == TOK_RWORD_REF ) + { + throw ParseError::Todo("ref bindings"); + tok = lex.getToken(); + } + switch( tok.type() ) + { + 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, true); + if( path.length() == 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) { + lex.putback(tok); + return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name()); + } + lex.putback(tok); + } + // otherwise, it's a value check + if(0) + case TOK_DOUBLE_COLON: + // 2. Paths are enum/struct names + { + lex.putback(tok); + path = Parse_Path(lex, true, true); + } + switch( GET_TOK(tok, lex) ) + { + case TOK_PAREN_OPEN: + // A list of internal patterns + throw ParseError::Todo("nested patterns"); + default: + lex.putback(tok); + return AST::Pattern(AST::Pattern::TagValue(), ExprNode(ExprNode::TagNamedValue(), path)); + } + break; + case TOK_INTEGER: + return AST::Pattern( AST::Pattern::TagValue(), ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype()) ); + default: + throw ParseError::Unexpected(tok); + } +} + ExprNode Parse_ExprBlockNode(TokenStream& lex) { ::std::vector nodes; @@ -81,6 +133,22 @@ ExprNode Parse_ExprBlockNode(TokenStream& lex) return AST::ExprNode(ExprNode::TagBlock(), nodes); } +::std::vector Parse_ParenList(TokenStream& lex) +{ + ::std::vector rv; + Token tok; + GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); + if( (tok = lex.getToken()).type() != TOK_PAREN_CLOSE ) + { + lex.putback(tok); + do { + rv.push_back( Parse_Expr1(lex) ); + } while( (tok = lex.getToken()).type() == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + } + return rv; +} + // 0: Assign AST::ExprNode Parse_Expr0(TokenStream& lex) { @@ -108,9 +176,18 @@ AST::ExprNode Parse_ExprBlocks(TokenStream& lex) // 1. Get expression AST::ExprNode switch_val = Parse_Expr1(lex); GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - throw ParseError::Todo("match arms"); - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - //return AST::ExprNode(ExprNode::TagMatch, switch_val, ); + ::std::vector< ::std::pair > arms; + if( (tok = lex.getToken()).type() == TOK_BRACE_CLOSE ) + throw ParseError::Unexpected(tok, Token(TOK_BRACE_CLOSE)); + lex.putback(tok); + do { + AST::Pattern pat = Parse_Pattern(lex); + GET_CHECK_TOK(tok, lex, TOK_FATARROW); + AST::ExprNode val = Parse_Expr0(lex); + arms.push_back( ::std::make_pair(pat, val) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_BRACE_CLOSE); + return AST::ExprNode(ExprNode::TagMatch(), switch_val, arms); } case TOK_RWORD_IF: throw ParseError::Todo("if"); @@ -241,6 +318,7 @@ AST::ExprNode Parse_ExprFC(TokenStream& lex) AST::ExprNode val = Parse_ExprVal(lex); while(true) { + Token tok; switch((tok = lex.getToken()).type()) { case TOK_PAREN_OPEN: @@ -249,8 +327,10 @@ AST::ExprNode Parse_ExprFC(TokenStream& lex) break; case TOK_DOT: // Field access + throw ParseError::Todo("Field access"); break; default: + lex.putback(tok); return val; } } @@ -269,20 +349,22 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex) if(0) case TOK_DOUBLE_COLON: path = Parse_Path(lex, true, true); - switch( (tok = lex.getToken()).type() ) + switch( GET_TOK(tok, lex) ) { case TOK_BRACE_OPEN: // Structure literal throw ParseError::Todo("Structure literal"); break; - case TOK_PAREN_OPEN: + case TOK_PAREN_OPEN: { + lex.putback(tok); // Function call - throw ParseError::Todo("Function call / structure literal"); - break; + ::std::vector args = Parse_ParenList(lex); + return ExprNode(ExprNode::TagCallPath(), path, args); + } default: // Value lex.putback(tok); - throw ParseError::Todo("Variable/Constant"); + return ExprNode(ExprNode::TagNamedValue(), path); } case TOK_INTEGER: return ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype()); diff --git a/parse/root.cpp b/parse/root.cpp index f78e9c1f..642c538c 100644 --- a/parse/root.cpp +++ b/parse/root.cpp @@ -6,9 +6,8 @@ #include "common.hpp" #include -AST::Path Parse_Path(TokenStream& lex, bool is_abs, bool generic_ok) +AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, bool generic_ok) { - AST::Path path; Token tok; do { @@ -27,6 +26,14 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, bool generic_ok) return path; } +AST::Path Parse_Path(TokenStream& lex, bool is_abs, bool generic_ok) +{ + if( is_abs ) + return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_ok); + else + return Parse_PathFrom(lex, AST::Path(), generic_ok); +} + static const struct { const char* name; enum eCoreType type; -- cgit v1.2.3