summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge (bugs) <tpg@mutabah.net>2014-12-03 23:03:30 +0800
committerJohn Hodge (bugs) <tpg@mutabah.net>2014-12-03 23:03:30 +0800
commit627a71e3bff7ab13e4a472e2c3da7e917782edd9 (patch)
tree04cb1f2ed84ca9ad99fa73fc7eb13f55e0e6c2b8
parent3801b7afaf6a61bd4ac6d0b6568765852ce3dc75 (diff)
downloadmrust-627a71e3bff7ab13e4a472e2c3da7e917782edd9.tar.gz
Hacking in patterns
-rw-r--r--ast/ast.cpp33
-rw-r--r--ast/ast.hpp62
-rw-r--r--parse/common.hpp1
-rw-r--r--parse/expr.cpp98
-rw-r--r--parse/root.cpp11
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<ExprNode> nodes)
}
ExprNode::ExprNode(TagInteger, uint64_t value, enum eCoreType datatype)
{
-
+}
+ExprNode::ExprNode(TagCallPath, Path path, ::std::vector<ExprNode> args)
+{
+}
+ExprNode::ExprNode(TagMatch, ExprNode val, ::std::vector< ::std::pair<Pattern,ExprNode> > 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 <string>
#include <vector>
+#include <stdexcept>
#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<TypeParam> 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<ExprNode> args);
+
+ struct TagMatch {};
+ ExprNode(TagMatch, ExprNode val, ::std::vector< ::std::pair<Pattern,ExprNode> > 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<TypeParam> 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<ExprNode> nodes;
@@ -81,6 +133,22 @@ ExprNode Parse_ExprBlockNode(TokenStream& lex)
return AST::ExprNode(ExprNode::TagBlock(), nodes);
}
+::std::vector<AST::ExprNode> Parse_ParenList(TokenStream& lex)
+{
+ ::std::vector<ExprNode> 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<AST::Pattern, ExprNode> > 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<AST::ExprNode> 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 <cassert>
-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;