summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parse/expr.cpp83
-rw-r--r--src/parse/interpolated_fragment.hpp1
-rw-r--r--src/parse/lex.cpp12
-rw-r--r--src/parse/token.cpp52
-rw-r--r--src/parse/token.hpp4
5 files changed, 109 insertions, 43 deletions
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index fbcb00d7..56b28546 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -15,6 +15,7 @@
#include "common.hpp"
#include <iostream>
#include "tokentree.hpp"
+#include "interpolated_fragment.hpp"
using AST::ExprNode;
using AST::ExprNodeP;
@@ -23,6 +24,7 @@ static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){
//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); // common.hpp
ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
+ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool *add_silence);
//ExprNodeP Parse_Stmt(TokenStream& lex); // common.hpp
ExprNodeP Parse_Expr0(TokenStream& lex);
ExprNodeP Parse_IfStmt(TokenStream& lex);
@@ -138,6 +140,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/)
ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
{
Token tok;
+ ExprNodeP ret;
if( GET_TOK(tok, lex) == TOK_LIFETIME )
{
@@ -153,13 +156,13 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
return Parse_WhileStmt(lex, lifetime);
case TOK_RWORD_FOR:
return Parse_ForStmt(lex, lifetime);
- case TOK_RWORD_IF:
- return Parse_IfStmt(lex);
- case TOK_RWORD_MATCH:
- return Parse_Expr_Match(lex);
- case TOK_BRACE_OPEN:
- PUTBACK(tok, lex);
- return Parse_ExprBlockNode(lex);
+ //case TOK_RWORD_IF:
+ // return Parse_IfStmt(lex);
+ //case TOK_RWORD_MATCH:
+ // return Parse_Expr_Match(lex);
+ //case TOK_BRACE_OPEN:
+ // PUTBACK(tok, lex);
+ // return Parse_ExprBlockNode(lex);
default:
throw ParseError::Unexpected(lex, tok);
@@ -171,9 +174,6 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
{
case TOK_SEMICOLON:
return NEWNODE(AST::ExprNode_Tuple, ::std::vector<AST::ExprNodeP>());
- case TOK_BRACE_OPEN:
- PUTBACK(tok, lex);
- return Parse_ExprBlockNode(lex);
// let binding
case TOK_RWORD_LET: {
@@ -190,20 +190,37 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), ::std::move(type), ::std::move(val) );
}
- // blocks that don't need semicolons
+ // Blocks that don't need semicolons
+ // NOTE: If these are followed by a small set of tokens (`.` and `?`) then they are actually the start of an expression
+ // HACK: Parse here, but if the next token is one of the set store in a TOK_INTERPOLATED_EXPR and invoke the statement parser
case TOK_RWORD_LOOP:
- return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
+ ret = NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
+ if(0)
case TOK_RWORD_WHILE:
- return Parse_WhileStmt(lex, "");
+ ret = Parse_WhileStmt(lex, "");
+ if(0)
case TOK_RWORD_FOR:
- return Parse_ForStmt(lex, "");
+ ret = Parse_ForStmt(lex, "");
+ if(0)
case TOK_RWORD_IF:
- return Parse_IfStmt(lex);
+ ret = Parse_IfStmt(lex);
+ if(0)
case TOK_RWORD_MATCH:
- return Parse_Expr_Match(lex);
+ ret = Parse_Expr_Match(lex);
+ if(0)
case TOK_RWORD_UNSAFE:
- return Parse_ExprBlockNode(lex, true);
+ ret = Parse_ExprBlockNode(lex, true);
+ if(0)
+ case TOK_BRACE_OPEN:
+ { PUTBACK(tok, lex); ret = Parse_ExprBlockNode(lex); }
+
+ if( lex.lookahead(0) == TOK_DOT || lex.lookahead(0) == TOK_QMARK ) {
+ lex.putback( Token(Token::TagTakeIP(), InterpolatedFragment(InterpolatedFragment::EXPR, ret.release())) );
+ return Parse_ExprBlockLine_Stmt(lex, add_silence);
+ }
+ return ret;
+ // Flow control
case TOK_RWORD_RETURN:
case TOK_RWORD_CONTINUE:
case TOK_RWORD_BREAK: {
@@ -225,23 +242,29 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
return Parse_ExprMacro(lex, tok);
}
// Fall through to the statement code
- default: {
+ default:
PUTBACK(tok, lex);
- auto ret = Parse_Stmt(lex);
- // 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);
- }
- else {
- *add_silence = true;
- }
- return ret;
- }
+ return Parse_ExprBlockLine_Stmt(lex, add_silence);
}
}
}
+
+ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool *add_silence)
+{
+ Token tok;
+ auto ret = Parse_Stmt(lex);
+ // 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);
+ }
+ else {
+ *add_silence = true;
+ }
+ return ret;
+}
+
/// While loop (either as a statement, or as part of an expression)
ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime)
{
diff --git a/src/parse/interpolated_fragment.hpp b/src/parse/interpolated_fragment.hpp
index db2c770f..7d9ee7c8 100644
--- a/src/parse/interpolated_fragment.hpp
+++ b/src/parse/interpolated_fragment.hpp
@@ -30,6 +30,7 @@ public:
META,
} m_type;
+ // Owned type-pruned pointer
void* m_ptr;
InterpolatedFragment(InterpolatedFragment&& );
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index 5fd10cf3..4a50d659 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -814,7 +814,17 @@ uint32_t Lexer::parseEscape(char enclosing)
auto ch = this->getc();
switch(ch.v)
{
- case 'x':
+ case 'x': {
+ ch = this->getc();
+ if( !ch.isxdigit() )
+ throw ParseError::Generic(*this, FMT("Found invalid character '\\x" << ::std::hex << ch.v << "' in \\u sequence" ) );
+ char tmp[3] = {static_cast<char>(ch.v), 0, 0};
+ ch = this->getc();
+ if( !ch.isxdigit() )
+ throw ParseError::Generic(*this, FMT("Found invalid character '\\x" << ::std::hex << ch.v << "' in \\u sequence" ) );
+ tmp[1] = static_cast<char>(ch.v);
+ return ::std::strtol(tmp, NULL, 16);
+ } break;
case 'u': {
// Unicode (up to six hex digits)
uint32_t val = 0;
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index 3f95d9fd..ee884d3b 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -63,38 +63,68 @@ Token::Token(double val, enum eCoreType datatype):
m_data( Data::make_Float({datatype, val}) )
{
}
-Token::Token(InterpolatedFragment& frag)
+Token::Token(const InterpolatedFragment& frag)
{
switch(frag.m_type)
{
case InterpolatedFragment::TT: throw "";
case InterpolatedFragment::TYPE:
m_type = TOK_INTERPOLATED_TYPE;
- m_data = new TypeRef( *reinterpret_cast<TypeRef*>(frag.m_ptr) );
+ m_data = new TypeRef( *reinterpret_cast<const TypeRef*>(frag.m_ptr) );
break;
case InterpolatedFragment::PAT:
m_type = TOK_INTERPOLATED_PATTERN;
- m_data = new AST::Pattern( reinterpret_cast<AST::Pattern*>(frag.m_ptr)->clone() );
+ m_data = new AST::Pattern( reinterpret_cast<const AST::Pattern*>(frag.m_ptr)->clone() );
break;
case InterpolatedFragment::PATH:
m_type = TOK_INTERPOLATED_PATH;
- m_data = new AST::Path( *reinterpret_cast<AST::Path*>(frag.m_ptr) );
+ m_data = new AST::Path( *reinterpret_cast<const AST::Path*>(frag.m_ptr) );
break;
case InterpolatedFragment::EXPR:
- m_type = TOK_INTERPOLATED_EXPR;
- m_data = reinterpret_cast<AST::ExprNode*>(frag.m_ptr)->clone().release();
- break;
+ m_type = TOK_INTERPOLATED_EXPR; if(0)
case InterpolatedFragment::STMT:
- m_type = TOK_INTERPOLATED_STMT;
- m_data = reinterpret_cast<AST::ExprNode*>(frag.m_ptr)->clone().release();
+ m_type = TOK_INTERPOLATED_STMT; if(0)
+ case InterpolatedFragment::BLOCK:
+ m_type = TOK_INTERPOLATED_BLOCK;
+
+ m_data = reinterpret_cast<const AST::ExprNode*>(frag.m_ptr)->clone().release();
+ break;
+ case InterpolatedFragment::META:
+ m_type = TOK_INTERPOLATED_META;
+ m_data = new AST::MetaItem( reinterpret_cast<const AST::MetaItem*>(frag.m_ptr)->clone() );
break;
+ }
+}
+Token::Token(TagTakeIP, InterpolatedFragment frag)
+{
+ switch(frag.m_type)
+ {
+ case InterpolatedFragment::TT: throw "";
+ case InterpolatedFragment::TYPE:
+ m_type = TOK_INTERPOLATED_TYPE;
+ m_data = new TypeRef( mv$(*reinterpret_cast<TypeRef*>(frag.m_ptr)) );
+ break;
+ case InterpolatedFragment::PAT:
+ m_type = TOK_INTERPOLATED_PATTERN;
+ m_data = new AST::Pattern( mv$(*reinterpret_cast<AST::Pattern*>(frag.m_ptr)) );
+ break;
+ case InterpolatedFragment::PATH:
+ m_type = TOK_INTERPOLATED_PATH;
+ m_data = new AST::Path( mv$(*reinterpret_cast<AST::Path*>(frag.m_ptr)) );
+ break;
+ case InterpolatedFragment::EXPR:
+ m_type = TOK_INTERPOLATED_EXPR; if(0)
+ case InterpolatedFragment::STMT:
+ m_type = TOK_INTERPOLATED_STMT; if(0)
case InterpolatedFragment::BLOCK:
m_type = TOK_INTERPOLATED_BLOCK;
- m_data = reinterpret_cast<AST::ExprNode*>(frag.m_ptr)->clone().release();
+
+ m_data = reinterpret_cast<AST::ExprNode*>(frag.m_ptr);
+ frag.m_ptr = nullptr;
break;
case InterpolatedFragment::META:
m_type = TOK_INTERPOLATED_META;
- m_data = new AST::MetaItem( reinterpret_cast<AST::MetaItem*>(frag.m_ptr)->clone() );
+ m_data = new AST::MetaItem( mv$(*reinterpret_cast<AST::MetaItem*>(frag.m_ptr)) );
break;
}
}
diff --git a/src/parse/token.hpp b/src/parse/token.hpp
index 25993b2f..93ce9c6c 100644
--- a/src/parse/token.hpp
+++ b/src/parse/token.hpp
@@ -103,7 +103,9 @@ public:
Token(enum eTokenType type, ::std::string str);
Token(uint64_t val, enum eCoreType datatype);
Token(double val, enum eCoreType datatype);
- Token(InterpolatedFragment& );
+ Token(const InterpolatedFragment& );
+ struct TagTakeIP {};
+ Token(TagTakeIP, InterpolatedFragment );
enum eTokenType type() const { return m_type; }
const ::std::string& str() const { return m_data.as_String(); }