summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-08 23:58:56 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-08 23:58:56 +0800
commitb082aab8d49e3b5a2e1eeee97fd9330f782b7381 (patch)
tree5eb644019f9b1eca222258453bcc54ff266e40fe
parent54ab187e82a41f7221660c7b1dc7777ce8a17228 (diff)
downloadmrust-b082aab8d49e3b5a2e1eeee97fd9330f782b7381.tar.gz
Cleanup to pattern handling
-rw-r--r--src/ast/expr.cpp4
-rw-r--r--src/ast/expr.hpp2
-rw-r--r--src/ast/pattern.hpp9
-rw-r--r--src/convert/resolve.cpp2
-rw-r--r--src/dump_as_rust.cpp2
-rw-r--r--src/parse/eTokenType.enum.h2
-rw-r--r--src/parse/expr.cpp99
-rw-r--r--src/parse/lex.cpp1
-rw-r--r--src/parse/root.cpp2
9 files changed, 75 insertions, 48 deletions
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<Pattern> 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<AST::Pattern> 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<AST::Pattern> 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<AST::Pattern> Parse_PatternList(TokenStream& lex)
{
+ TRACE_FUNCTION;
Token tok;
::std::vector<AST::Pattern> 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<ExprNodeP> 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 )