diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/macros.cpp | 2 | ||||
-rw-r--r-- | src/parse/common.hpp | 4 | ||||
-rw-r--r-- | src/parse/expr.cpp | 248 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 264 |
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)); +} + |