summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/macros.cpp2
-rw-r--r--src/parse/common.hpp4
-rw-r--r--src/parse/expr.cpp248
-rw-r--r--src/parse/pattern.cpp264
4 files changed, 269 insertions, 249 deletions
diff --git a/src/macros.cpp b/src/macros.cpp
index fe833dde..26e8ada4 100644
--- a/src/macros.cpp
+++ b/src/macros.cpp
@@ -539,9 +539,9 @@ Position MacroExpander::getPosition() const
Token MacroExpander::realGetToken()
{
// Use m_next_token first
- DEBUG("m_next_token = " << m_next_token);
if( m_next_token.type() != TOK_NULL )
{
+ DEBUG("m_next_token = " << m_next_token);
return ::std::move(m_next_token);
}
// Then try m_ttstream
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index da6a7009..87c63bb9 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -30,8 +30,12 @@ extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mo
extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
extern AST::Path Parse_PathFrom(TokenStream& lex, AST::Path src, eParsePathGenericMode generic_mode);
extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
+
extern TypeRef Parse_Type(TokenStream& lex);
+
+extern AST::Pattern Parse_Pattern(TokenStream& lex);
+
extern void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn);
extern void Parse_Struct(AST::Module& mod, TokenStream& lex, bool is_public, const AST::MetaItems meta_items);
extern AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe=false);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index fdedcb1b..0e434c8c 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -30,254 +30,6 @@ AST::Expr Parse_ExprBlock(TokenStream& lex)
return AST::Expr(Parse_ExprBlockNode(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);
-AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path);
-
-
-/// Parse a pattern
-///
-/// Examples:
-/// - `Enum::Variant(a)`
-/// - `(1, a)`
-/// - `1 ... 2`
-/// - `"string"`
-/// - `mut x`
-/// - `mut x @ 1 ... 2`
-AST::Pattern Parse_Pattern(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- Token tok;
- tok = lex.getToken();
-
- bool expect_bind = false;
- bool is_mut = false;
- bool is_ref = false;
- // 1. Mutablity + Reference
- if( tok.type() == TOK_RWORD_REF )
- {
- is_ref = true;
- expect_bind = true;
- tok = lex.getToken();
- }
- if( tok.type() == TOK_RWORD_MUT )
- {
- is_mut = true;
- expect_bind = true;
- tok = lex.getToken();
- }
-
- ::std::string bind_name;
- // If a 'ref' or 'mut' annotation was seen, the next name must be a binding name
- if( expect_bind )
- {
- CHECK_TOK(tok, TOK_IDENT);
- bind_name = tok.str();
- // If there's no '@' after it, it's a name binding only (_ pattern)
- if( GET_TOK(tok, lex) != TOK_AT )
- {
- lex.putback(tok);
- return AST::Pattern(AST::Pattern::TagBind(), bind_name);
- }
-
- tok = lex.getToken();
- }
- // Otherwise, handle MaybeBind
- else if( tok.type() == TOK_IDENT )
- {
- lex.putback(tok);
- AST::Path path = Parse_Path(lex, false, PATH_GENERIC_EXPR);
- // - If the path is trivial
- if( path.size() == 1 && path[0].args().size() == 0 )
- {
- 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);
- // - Fall though
- break;
- // - Else, if the next token is a '(' or '{', treat as a struct/enum
- case TOK_BRACE_OPEN:
- case TOK_PAREN_OPEN:
- lex.putback(tok);
- return Parse_PatternReal_Path(lex, path);
- // - Else, treat as a MaybeBind
- default:
- lex.putback(tok);
- return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name());
- }
- }
- else
- {
- // 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 ::std::move(pat);
-}
-
-AST::Pattern Parse_PatternReal(TokenStream& lex);
-AST::Pattern Parse_PatternReal1(TokenStream& lex);
-
-AST::Pattern Parse_PatternReal(TokenStream& lex)
-{
- Token tok;
- AST::Pattern ret = Parse_PatternReal1(lex);
- if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT )
- {
- if( !ret.data().is_Value() )
- throw ParseError::Generic(lex, "Using '...' with a non-value on left");
- auto leftval = ret.take_node();
- auto right_pat = Parse_PatternReal1(lex);
- if( !right_pat.data().is_Value() )
- throw ParseError::Generic(lex, "Using '...' with a non-value on right");
- auto rightval = right_pat.take_node();
-
- return AST::Pattern(AST::Pattern::TagValue(), ::std::move(leftval), ::std::move(rightval));
- }
- else
- {
- lex.putback(tok);
- return ret;
- }
-}
-AST::Pattern Parse_PatternReal1(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- Token tok;
- AST::Path path;
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_UNDERSCORE:
- return AST::Pattern( );
- case TOK_DOUBLE_DOT:
- return AST::Pattern( AST::Pattern::TagWildcard() );
- case TOK_AMP:
- DEBUG("Ref");
- if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
- // TODO: Actually use mutability
- return AST::Pattern( AST::Pattern::TagReference(), Parse_PatternReal(lex) );
- lex.putback(tok);
- return AST::Pattern( AST::Pattern::TagReference(), Parse_PatternReal(lex) );
- case TOK_IDENT:
- lex.putback(tok);
- return Parse_PatternReal_Path( lex, Parse_Path(lex, false, PATH_GENERIC_EXPR) );
- case TOK_DOUBLE_COLON:
- // 2. Paths are enum/struct names
- return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR) );
- case TOK_DASH:
- GET_CHECK_TOK(tok, lex, TOK_INTEGER);
- return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, -tok.intval(), tok.datatype()) );
- case TOK_INTEGER:
- return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, tok.intval(), tok.datatype()) );
- case TOK_RWORD_TRUE:
- return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, true ) );
- case TOK_RWORD_FALSE:
- return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, false ) );
- case TOK_STRING:
- return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) );
- case TOK_PAREN_OPEN:
- return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex));
- case TOK_SQUARE_OPEN:
- throw ParseError::Todo(lex, "array patterns");
- default:
- throw ParseError::Unexpected(lex, tok);
- }
-}
-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));
- case TOK_BRACE_OPEN:
- return Parse_PatternStruct(lex, ::std::move(path));
- 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;
-
- auto end = TOK_PAREN_CLOSE;
- do {
- if( GET_TOK(tok, lex) == end )
- break;
- else
- lex.putback(tok);
-
- AST::Pattern pat = Parse_Pattern(lex);
- DEBUG("pat = " << pat);
- child_pats.push_back( ::std::move(pat) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, end);
- return child_pats;
-}
-
-AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats;
- do {
- GET_TOK(tok, lex);
- DEBUG("tok = " << tok);
- if( tok.type() == TOK_BRACE_CLOSE )
- break;
- if( tok.type() == TOK_DOUBLE_DOT ) {
- GET_TOK(tok, lex);
- break;
- }
-
- bool is_short_bind = false;
- if( tok.type() == TOK_RWORD_REF ) {
- is_short_bind = true;
- GET_TOK(tok, lex);
- }
- if( tok.type() == TOK_RWORD_MUT ) {
- is_short_bind = true;
- GET_TOK(tok, lex);
- }
-
- CHECK_TOK(tok, TOK_IDENT);
- ::std::string field = tok.str();
- GET_TOK(tok, lex);
-
- AST::Pattern pat;
- if( is_short_bind || tok.type() != TOK_COLON ) {
- lex.putback(tok);
- pat = AST::Pattern(AST::Pattern::TagBind(), field);
- }
- else {
- CHECK_TOK(tok, TOK_COLON);
- pat = Parse_Pattern(lex);
- }
- // TODO: Append
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
- return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats));
-}
-
ExprNodeP Parse_ExprBlockNode(TokenStream& lex);
ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end);
void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Item<AST::Function> >& imports);
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
new file mode 100644
index 00000000..7113f94b
--- /dev/null
+++ b/src/parse/pattern.cpp
@@ -0,0 +1,264 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/pattern.cpp
+ * - Parsing for patterns
+ */
+#include "common.hpp"
+#include "parseerror.hpp"
+
+// NEWNODE is needed for the Value pattern type
+typedef ::std::unique_ptr<AST::ExprNode> ExprNodeP;
+#define NEWNODE(type, ...) ExprNodeP(new type(__VA_ARGS__))
+using AST::ExprNode;
+
+
+::std::vector<AST::Pattern> Parse_PatternList(TokenStream& lex);
+
+AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path);
+AST::Pattern Parse_PatternReal(TokenStream& lex);
+AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path);
+
+
+/// Parse a pattern
+///
+/// Examples:
+/// - `Enum::Variant(a)`
+/// - `(1, a)`
+/// - `1 ... 2`
+/// - `"string"`
+/// - `mut x`
+/// - `mut x @ 1 ... 2`
+AST::Pattern Parse_Pattern(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ tok = lex.getToken();
+
+ bool expect_bind = false;
+ bool is_mut = false;
+ bool is_ref = false;
+ // 1. Mutablity + Reference
+ if( tok.type() == TOK_RWORD_REF )
+ {
+ is_ref = true;
+ expect_bind = true;
+ tok = lex.getToken();
+ }
+ if( tok.type() == TOK_RWORD_MUT )
+ {
+ is_mut = true;
+ expect_bind = true;
+ tok = lex.getToken();
+ }
+
+ ::std::string bind_name;
+ // If a 'ref' or 'mut' annotation was seen, the next name must be a binding name
+ if( expect_bind )
+ {
+ CHECK_TOK(tok, TOK_IDENT);
+ bind_name = tok.str();
+ // If there's no '@' after it, it's a name binding only (_ pattern)
+ if( GET_TOK(tok, lex) != TOK_AT )
+ {
+ lex.putback(tok);
+ return AST::Pattern(AST::Pattern::TagBind(), bind_name);
+ }
+
+ tok = lex.getToken();
+ }
+ // Otherwise, handle MaybeBind
+ else if( tok.type() == TOK_IDENT )
+ {
+ lex.putback(tok);
+ AST::Path path = Parse_Path(lex, false, PATH_GENERIC_EXPR);
+ // - If the path is trivial
+ if( path.size() == 1 && path[0].args().size() == 0 )
+ {
+ 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);
+ // - Fall though
+ break;
+ // - Else, if the next token is a '(' or '{', treat as a struct/enum
+ case TOK_BRACE_OPEN:
+ case TOK_PAREN_OPEN:
+ lex.putback(tok);
+ return Parse_PatternReal_Path(lex, path);
+ // - Else, treat as a MaybeBind
+ default:
+ lex.putback(tok);
+ return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name());
+ }
+ }
+ else
+ {
+ // 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 ::std::move(pat);
+}
+
+AST::Pattern Parse_PatternReal(TokenStream& lex);
+AST::Pattern Parse_PatternReal1(TokenStream& lex);
+
+AST::Pattern Parse_PatternReal(TokenStream& lex)
+{
+ Token tok;
+ AST::Pattern ret = Parse_PatternReal1(lex);
+ if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT )
+ {
+ if( !ret.data().is_Value() )
+ throw ParseError::Generic(lex, "Using '...' with a non-value on left");
+ auto leftval = ret.take_node();
+ auto right_pat = Parse_PatternReal1(lex);
+ if( !right_pat.data().is_Value() )
+ throw ParseError::Generic(lex, "Using '...' with a non-value on right");
+ auto rightval = right_pat.take_node();
+
+ return AST::Pattern(AST::Pattern::TagValue(), ::std::move(leftval), ::std::move(rightval));
+ }
+ else
+ {
+ lex.putback(tok);
+ return ret;
+ }
+}
+AST::Pattern Parse_PatternReal1(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ AST::Path path;
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_UNDERSCORE:
+ return AST::Pattern( );
+ case TOK_DOUBLE_DOT:
+ return AST::Pattern( AST::Pattern::TagWildcard() );
+ case TOK_AMP:
+ DEBUG("Ref");
+ if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
+ // TODO: Actually use mutability
+ return AST::Pattern( AST::Pattern::TagReference(), Parse_PatternReal(lex) );
+ lex.putback(tok);
+ return AST::Pattern( AST::Pattern::TagReference(), Parse_PatternReal(lex) );
+ case TOK_IDENT:
+ lex.putback(tok);
+ return Parse_PatternReal_Path( lex, Parse_Path(lex, false, PATH_GENERIC_EXPR) );
+ case TOK_DOUBLE_COLON:
+ // 2. Paths are enum/struct names
+ return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR) );
+ case TOK_DASH:
+ GET_CHECK_TOK(tok, lex, TOK_INTEGER);
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, -tok.intval(), tok.datatype()) );
+ case TOK_INTEGER:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, tok.intval(), tok.datatype()) );
+ case TOK_RWORD_TRUE:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, true ) );
+ case TOK_RWORD_FALSE:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, false ) );
+ case TOK_STRING:
+ return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) );
+ case TOK_PAREN_OPEN:
+ return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex));
+ case TOK_SQUARE_OPEN:
+ throw ParseError::Todo(lex, "array patterns");
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+}
+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));
+ case TOK_BRACE_OPEN:
+ return Parse_PatternStruct(lex, ::std::move(path));
+ 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;
+
+ auto end = TOK_PAREN_CLOSE;
+ do {
+ if( GET_TOK(tok, lex) == end )
+ break;
+ else
+ lex.putback(tok);
+
+ AST::Pattern pat = Parse_Pattern(lex);
+ DEBUG("pat = " << pat);
+ child_pats.push_back( ::std::move(pat) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, end);
+ return child_pats;
+}
+
+AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ ::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats;
+ do {
+ GET_TOK(tok, lex);
+ DEBUG("tok = " << tok);
+ if( tok.type() == TOK_BRACE_CLOSE )
+ break;
+ if( tok.type() == TOK_DOUBLE_DOT ) {
+ GET_TOK(tok, lex);
+ break;
+ }
+
+ bool is_short_bind = false;
+ if( tok.type() == TOK_RWORD_REF ) {
+ is_short_bind = true;
+ GET_TOK(tok, lex);
+ }
+ if( tok.type() == TOK_RWORD_MUT ) {
+ is_short_bind = true;
+ GET_TOK(tok, lex);
+ }
+
+ CHECK_TOK(tok, TOK_IDENT);
+ ::std::string field = tok.str();
+ GET_TOK(tok, lex);
+
+ AST::Pattern pat;
+ if( is_short_bind || tok.type() != TOK_COLON ) {
+ lex.putback(tok);
+ pat = AST::Pattern(AST::Pattern::TagBind(), field);
+ }
+ else {
+ CHECK_TOK(tok, TOK_COLON);
+ pat = Parse_Pattern(lex);
+ }
+ // TODO: Append
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats));
+}
+