From d7cff94061f2c42095e91ca5c30cffde03974cdc Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 12 Jun 2016 14:00:32 +0800 Subject: Parse - Fix incorrect handling of trailing semicolons --- src/ast/ast.cpp | 3 +++ src/parse/expr.cpp | 59 ++++++++++++++++-------------------------------------- src/parse/root.cpp | 1 + 3 files changed, 21 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 77981a4d..8af991c0 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -105,6 +105,7 @@ SERIALISE_TYPE(ImplDef::, "AST_ImplDef", { void Impl::add_function(bool is_public, ::std::string name, Function fcn) { + DEBUG("impl fn " << name); m_items.push_back( Named( mv$(name), Item::make_Function({::std::move(fcn)}), is_public ) ); } void Impl::add_type(bool is_public, ::std::string name, TypeRef type) @@ -247,6 +248,7 @@ void Module::add_enum(bool is_public, ::std::string name, Enum item, MetaItems a this->add_item( is_public, name, Item::make_Enum({mv$(item)}), mv$(attrs) ); } void Module::add_function(bool is_public, ::std::string name, Function item, MetaItems attrs) { + DEBUG("mod fn " << name); this->add_item( is_public, name, Item::make_Function({mv$(item)}), mv$(attrs) ); } void Module::add_submod(bool is_public, ::std::string name, Module mod, MetaItems attrs) { @@ -452,6 +454,7 @@ void Trait::add_type(::std::string name, TypeRef type) { m_items.push_back( Named(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) ); } void Trait::add_function(::std::string name, Function fcn) { + DEBUG("trait fn " << name); m_items.push_back( Named(mv$(name), Item::make_Function({mv$(fcn)}), true) ); } void Trait::add_static(::std::string name, Static v) { diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 3dbdd1d3..f01272f6 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -22,7 +22,7 @@ static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){ #define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__)) ExprNodeP Parse_ExprBlockNode(TokenStream& lex); -ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end); +ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence); ExprNodeP Parse_Stmt(TokenStream& lex); ExprNodeP Parse_Expr0(TokenStream& lex); ExprNodeP Parse_IfStmt(TokenStream& lex); @@ -105,8 +105,8 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) // fall default: { PUTBACK(tok, lex); - bool expect_end = false; - nodes.push_back(Parse_ExprBlockLine(lex, &expect_end)); + bool add_silence_if_end = false; + nodes.push_back(Parse_ExprBlockLine(lex, &add_silence_if_end)); if( nodes.back() ) { nodes.back()->set_attrs( mv$(item_attrs) ); } @@ -114,14 +114,11 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) // TODO: Error if attribute on void expression? } // Set to TRUE if there was no semicolon after a statement - if( expect_end ) + if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE && add_silence_if_end ) { - DEBUG("expect_end == true"); - if( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - throw ParseError::Unexpected(lex, tok, Token(TOK_BRACE_CLOSE)); - } - PUTBACK(tok, lex); + DEBUG("expect_end == false, end of block"); + nodes.push_back( NEWNODE(AST::ExprNode_Tuple, ::std::vector()) ); + // NOTE: Would break, but we're in a switch } break; } @@ -136,7 +133,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) /// Handles: /// - Block-level constructs (with lifetime annotations) /// - use/extern/const/let -ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) +ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence) { Token tok; @@ -171,7 +168,7 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) switch( tok.type() ) { case TOK_SEMICOLON: - return 0; + return NEWNODE(AST::ExprNode_Tuple, ::std::vector()); case TOK_BRACE_OPEN: PUTBACK(tok, lex); return Parse_ExprBlockNode(lex); @@ -217,13 +214,16 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) default: { PUTBACK(tok, lex); auto ret = Parse_Stmt(lex); - if( GET_TOK(tok, lex) != TOK_SEMICOLON ) - { + // If this expression statement wasn't followed by a semicolon, then it's yielding its value out of the block. + // - I.e. The block should be ending + if( GET_TOK(tok, lex) != TOK_SEMICOLON ) { + CHECK_TOK(tok, TOK_BRACE_CLOSE); PUTBACK(tok, lex); - *expect_end = true; } - return ::std::move(ret); - break; + else { + *add_silence = true; + } + return ret; } } } @@ -911,31 +911,6 @@ ExprNodeP Parse_ExprVal_Closure(TokenStream& lex, bool is_move) return NEWNODE( AST::ExprNode_Closure, ::std::move(args), ::std::move(rt), ::std::move(code) ); } -ExprNodeP Parse_FormatArgs(TokenStream& lex) -{ - TRACE_FUNCTION; - - Token tok; - - GET_CHECK_TOK(tok, lex, TOK_STRING); - ::std::string fmt = tok.str(); - - ::std::vector nodes; - - while( GET_TOK(tok, lex) == TOK_COMMA ) - { - // TODO: Support named - auto exp = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, Parse_Expr1(lex) ); - - // ( &arg as *const _, &::fmt as fn(*const (), &mut Formatter) ) - //nodes.push_back( NEWNODE( AST::ExprNode_Cast, TypeRef - } - - //return NEWNODE( AST::ExprNode_ArrayLiteral, ::std::move(nodes) ); - DEBUG("TODO: Proper support for format_args!"); - return NEWNODE( AST::ExprNode_Tuple, ::std::vector() ); -} - ExprNodeP Parse_ExprVal(TokenStream& lex) { TRACE_FUNCTION; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 1e57227e..7dfb6f2c 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -1040,6 +1040,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); + DEBUG("Function " << name); // - 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)); -- cgit v1.2.3