From 756abd3f2fd768e73a014e190c7a446a3f5aa44c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 30 Apr 2016 13:05:14 +0800 Subject: Parser - Handle '?', '...', and 'default fn` --- src/ast/expr.cpp | 6 ++++++ src/ast/expr.hpp | 12 +++++++----- src/dump_as_rust.cpp | 11 ++++++++++- src/parse/expr.cpp | 14 ++++++++++++-- src/parse/root.cpp | 34 +++++++++++++++++++++++++++++----- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 49ebdbe2..a2f9cbd1 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -380,6 +380,7 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { _(CMPGT); _(CMPGTE); _(RANGE); + _(RANGE_INC); _(BOOLAND); _(BOOLOR); _(BITAND); @@ -408,6 +409,7 @@ void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) { _(CMPGT); _(CMPGTE); _(RANGE); + _(RANGE_INC); _(BOOLAND); _(BOOLOR); _(BITAND); @@ -451,6 +453,7 @@ NODE(ExprNode_BinOp, { case ADD: os << "+"; break; case SUB: os << "-"; break; case RANGE: os << ".."; break; + case RANGE_INC: os << "..."; break; case PLACE_IN: os << "<-"; break; } os << " " << *m_right << ")"; @@ -465,6 +468,7 @@ void operator%(::Serialiser& s, const ExprNode_UniOp::Type t) { _(BOX) _(REF) _(REFMUT) + _(QMARK) #undef _ } } @@ -478,6 +482,7 @@ void operator%(::Deserialiser& s, enum ExprNode_UniOp::Type& t) { _(BOX) _(REF) _(REFMUT) + _(QMARK) #undef _ else throw ::std::runtime_error( FMT("No uniop type for '" << n << "'") ); @@ -493,6 +498,7 @@ NODE(ExprNode_UniOp, { case BOX: os << "(box "; break; case REF: os << "(&"; break; case REFMUT: os << "(&mut "; break; + case QMARK: os << "(" << *m_value << "?)"; return; } os << *m_value << ")"; }) diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 19b7cddc..19c348cb 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -513,6 +513,7 @@ struct ExprNode_BinOp: CMPGTE, RANGE, + RANGE_INC, BOOLAND, BOOLOR, @@ -551,11 +552,12 @@ struct ExprNode_UniOp: public ExprNode { enum Type { - REF, - REFMUT, - BOX, - INVERT, - NEGATE, + REF, // '& ' + REFMUT, // '&mut ' + BOX, // 'box ' + INVERT, // '!' + NEGATE, // '-' + QMARK, // '?' }; enum Type m_type; diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index f72b2df5..357795c5 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -487,6 +487,7 @@ public: case AST::ExprNode_BinOp::ADD: m_os << "+"; break; case AST::ExprNode_BinOp::SUB: m_os << "-"; break; case AST::ExprNode_BinOp::RANGE: m_os << ".."; break; + case AST::ExprNode_BinOp::RANGE_INC: m_os << "..."; break; case AST::ExprNode_BinOp::PLACE_IN: m_os << "<-"; break; } m_os << " "; @@ -504,11 +505,19 @@ public: case AST::ExprNode_UniOp::BOX: m_os << "box "; break; case AST::ExprNode_UniOp::REF: m_os << "&"; break; case AST::ExprNode_UniOp::REFMUT: m_os << "&mut "; break; + case AST::ExprNode_UniOp::QMARK: break; } if( IS(*n.m_value, AST::ExprNode_BinOp) ) - m_os << " "; + m_os << "("; AST::NodeVisitor::visit(n.m_value); + if( IS(*n.m_value, AST::ExprNode_BinOp) ) + m_os << ")"; + switch(n.m_type) + { + case AST::ExprNode_UniOp::QMARK: m_os << "?"; break; + default: break; + } } diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 58c82a0b..407afbf3 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -578,12 +578,12 @@ bool Parse_IsTokValue(eTokenType tok_type) } } -ExprNodeP Parse_Expr1_5(TokenStream& lex); +ExprNodeP Parse_Expr1_1(TokenStream& lex); // Very evil handling for '..' ExprNodeP Parse_Expr1(TokenStream& lex) { Token tok; - ExprNodeP (*next)(TokenStream&) = Parse_Expr1_5; + ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1; ExprNodeP left, right; if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT ) @@ -610,6 +610,12 @@ ExprNodeP Parse_Expr1(TokenStream& lex) return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) ); } +// TODO: Is this left associative? +LEFTASSOC(Parse_Expr1_1, Parse_Expr1_5, + case TOK_TRIPLE_DOT: + rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) ); + break; +) // 1: Bool OR LEFTASSOC(Parse_Expr1_5, Parse_Expr2, case TOK_DOUBLE_PIPE: @@ -765,6 +771,10 @@ ExprNodeP Parse_ExprFC(TokenStream& lex) Token tok; switch(GET_TOK(tok, lex)) { + case TOK_QMARK: + val = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::QMARK, mv$(val) ); + break; + case TOK_PAREN_OPEN: // Expression method call lex.putback(tok); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 4aba4874..0ce6935b 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -972,7 +972,8 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; } case TOK_RWORD_CONST: - if( GET_TOK(tok, lex) != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE ) + GET_TOK(tok, lex); + if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE ) { CHECK_TOK(tok, TOK_IDENT); auto name = mv$(tok.str()); @@ -989,11 +990,14 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) } else if( tok.type() == TOK_RWORD_UNSAFE ) { - if( GET_TOK(tok, lex) != TOK_RWORD_FN ) - ERROR(lex.end_span(lex.start_span()), E0000, ""); + GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); + // TODO: Use a better marker item_attrs.push_back( AST::MetaItem("#UNSAFE") ); } + // TODO: Mark `const fn` as const (properly) + item_attrs.push_back( AST::MetaItem("#CONST") ); if( 0 ) + // FALL case TOK_RWORD_EXTERN: { abi = "C"; @@ -1005,6 +1009,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) GET_TOK(tok, lex); } CHECK_TOK(tok, TOK_RWORD_FN); + // FALL case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); @@ -1012,6 +1017,21 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) auto fcn = Parse_FunctionDefWithCode(lex, abi, item_attrs, true); impl.add_function(is_public, ::std::move(name), mv$(fcn)); break; } + + case TOK_IDENT: + if( tok.str() == "default" ) { + // TODO: Mark `default` functions as default (i.e. specialisable) + GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + // - Self allowed, can't be prototype-form + auto fcn = Parse_FunctionDefWithCode(lex, abi, item_attrs, true); + impl.add_function(is_public, ::std::move(name), mv$(fcn)); + } + else { + throw ParseError::Unexpected(lex, tok); + } + break; default: throw ParseError::Unexpected(lex, tok); @@ -1340,13 +1360,16 @@ void Parse_Mod_Item(TokenStream& lex, bool file_controls_dir, const ::std::strin GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); GET_CHECK_TOK(tok, lex, TOK_IDENT); // TODO: Mark as const and unsafe + meta_items.push_back( AST::MetaItem("#UNSAFE") ); + meta_items.push_back( AST::MetaItem("#CONST") ); auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); break; } case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - // - self not allowed, not prototype // TODO: Mark as const + meta_items.push_back( AST::MetaItem("#CONST") ); + // - self not allowed, not prototype auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); break; } @@ -1403,8 +1426,9 @@ void Parse_Mod_Item(TokenStream& lex, bool file_controls_dir, const ::std::strin // `unsafe fn` case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - // - self not allowed, not prototype // TODO: Mark as unsafe + meta_items.push_back( AST::MetaItem("#UNSAFE") ); + // - self not allowed, not prototype auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); //i.set_unsafe(); mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); -- cgit v1.2.3