diff options
author | John Hodge (bugs) <tpg@mutabah.net> | 2014-12-07 09:46:00 +0800 |
---|---|---|
committer | John Hodge (bugs) <tpg@mutabah.net> | 2014-12-07 09:46:00 +0800 |
commit | c325b671c1a44c90c8ce570b901219bcc2ae0a38 (patch) | |
tree | 5dff25da15192ad0b0635fa96bab5f510df018c6 /parse | |
parent | 1ac5429531c195755c7e1690912291e20e9a1717 (diff) | |
download | mrust-c325b671c1a44c90c8ce570b901219bcc2ae0a38.tar.gz |
Macro evaluation hacked in (... not quite in yet, but framework is there)
Macro definitions not implemented, evil hack to define try! is present
Diffstat (limited to 'parse')
-rw-r--r-- | parse/expr.cpp | 162 | ||||
-rw-r--r-- | parse/lex.cpp | 50 | ||||
-rw-r--r-- | parse/lex.hpp | 42 | ||||
-rw-r--r-- | parse/parseerror.cpp | 12 | ||||
-rw-r--r-- | parse/parseerror.hpp | 18 | ||||
-rw-r--r-- | parse/preproc.cpp | 20 | ||||
-rw-r--r-- | parse/preproc.hpp | 6 | ||||
-rw-r--r-- | parse/root.cpp | 41 | ||||
-rw-r--r-- | parse/tokentree.hpp | 10 |
9 files changed, 319 insertions, 42 deletions
diff --git a/parse/expr.cpp b/parse/expr.cpp index 90a39b04..cb3b80e7 100644 --- a/parse/expr.cpp +++ b/parse/expr.cpp @@ -4,7 +4,9 @@ #include "parseerror.hpp"
#include "../ast/ast.hpp"
#include "common.hpp"
+#include "../macros.hpp"
#include <iostream>
+#include "tokentree.hpp"
using AST::ExprNode;
@@ -82,6 +84,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex) default:
throw ParseError::Unexpected(tok);
}
+ throw ParseError::BugCheck("Parse_TT_Stmt should early return");
}
ExprNode Parse_ExprBlockNode(TokenStream& lex)
@@ -102,12 +105,15 @@ ExprNode Parse_ExprBlockNode(TokenStream& lex) nodes.push_back(Parse_ExprBlockNode(lex));
trailing_value = true;
break;
- case TOK_RWORD_LET:
+ case TOK_RWORD_LET: {
//ret.append();
- throw ParseError::Todo("block let");
+ AST::Pattern pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ AST::ExprNode val = Parse_Expr1(lex);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
trailing_value = false;
- break;
+ nodes.push_back( ExprNode(ExprNode::TagLetBinding(), pat, val));
+ break; }
case TOK_RWORD_LOOP:
throw ParseError::Todo("loop");
break;
@@ -360,10 +366,31 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex) path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
switch( GET_TOK(tok, lex) )
{
- case TOK_BRACE_OPEN:
- // Structure literal
- throw ParseError::Todo("Structure literal");
- break;
+ case TOK_BRACE_OPEN: {
+ // Braced structure literal
+ // - A series of 0 or more pairs of <ident>: <expr>,
+ // - '..' <expr>
+ ::std::vector< ::std::pair< ::std::string, AST::ExprNode> > items;
+ while( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ AST::ExprNode val = Parse_Expr0(lex);
+ items.push_back( ::std::make_pair(name, val) );
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ AST::ExprNode base_val;
+ if( tok.type() == TOK_DOUBLE_DOT )
+ {
+ // default
+ base_val = Parse_Expr0(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ return ExprNode(ExprNode::TagStructLiteral(), path, base_val, items);
+ }
case TOK_PAREN_OPEN: {
lex.putback(tok);
// Function call
@@ -379,7 +406,128 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex) return ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype());
case TOK_FLOAT:
throw ParseError::Todo("Float");
+ case TOK_MACRO: {
+ // Need to create a token tree, pass to the macro, then pass the result of that to Parse_Expr0
+ MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), Parse_TT(lex));
+
+ return Parse_Expr0(expanded_macro);
+ }
default:
throw ParseError::Unexpected(tok);
}
}
+
+// Token Tree Parsing
+TokenTree Parse_TT(TokenStream& lex)
+{
+ Token tok = lex.getToken();
+ eTokenType closer = TOK_PAREN_CLOSE;
+ switch(tok.type())
+ {
+ case TOK_PAREN_OPEN:
+ closer = TOK_PAREN_CLOSE;
+ break;
+ case TOK_SQUARE_OPEN:
+ closer = TOK_SQUARE_CLOSE;
+ break;
+ case TOK_BRACE_OPEN:
+ closer = TOK_BRACE_CLOSE;
+ break;
+ default:
+ return TokenTree(tok);
+ }
+
+ ::std::vector<TokenTree> items;
+ items.push_back(tok);
+ while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF)
+ {
+ lex.putback(tok);
+ items.push_back(Parse_TT(lex));
+ }
+ items.push_back(tok);
+ return TokenTree(items);
+}
+
+TokenTree Parse_TT_Path(TokenStream& lex)
+{
+ throw ParseError::Todo("TokenTree path");
+}
+TokenTree Parse_TT_Val(TokenStream& lex)
+{
+ Token tok;
+ ::std::vector<TokenTree> ret;
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_PAREN_OPEN:
+ lex.putback(tok);
+ return Parse_TT(lex);
+
+ case TOK_IDENT:
+ case TOK_DOUBLE_COLON: {
+ lex.putback(tok);
+ TokenTree inner = Parse_TT_Path(lex);
+ if(GET_TOK(tok, lex) == TOK_BRACE_OPEN) {
+ lex.putback(tok);
+ ret.push_back(inner);
+ ret.push_back(Parse_TT(lex));
+ }
+ else {
+ lex.putback(tok);
+ return inner;
+ }
+ break; }
+ case TOK_RWORD_MATCH:
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ break;
+ case TOK_RWORD_IF:
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) {
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ }
+ else {
+ lex.putback(tok);
+ }
+ break;
+ default:
+ // Oh, fail :(
+ break;
+ }
+ return TokenTree(ret);
+}
+TokenTree Parse_TT_Expr(TokenStream& lex)
+{
+ Token tok;
+ ::std::vector<TokenTree> ret;
+
+ ret.push_back(Parse_TT_Val(lex));
+ // 1. Get left associative blocks until nothing matches
+ bool cont = true;
+ while(cont)
+ {
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_PLUS:
+ case TOK_DASH:
+ ret.push_back(tok);
+ ret.push_back(Parse_TT_Val(lex));
+ break;
+ default:
+ lex.putback(tok);
+ cont = false;
+ break;
+ }
+ }
+ return TokenTree(ret);
+
+}
+TokenTree Parse_TT_Stmt(TokenStream& lex)
+{
+ throw ParseError::Todo("Parse_TT_Stmt");
+}
+TokenTree Parse_TT_Block(TokenStream& lex)
+{
+ throw ParseError::Todo("Parse_TT_Block");
+}
diff --git a/parse/lex.cpp b/parse/lex.cpp index 99568a11..99d787fb 100644 --- a/parse/lex.cpp +++ b/parse/lex.cpp @@ -133,9 +133,9 @@ static const struct { TOKENT("pure", TOK_RWORD_PURE),
TOKENT("ref", TOK_RWORD_REF),
TOKENT("return", TOK_RWORD_RETURN),
+ TOKENT("self", TOK_RWORD_SELF),
TOKENT("sizeof", TOK_RWORD_SIZEOF),
TOKENT("static", TOK_RWORD_STATIC),
- TOKENT("self", TOK_RWORD_SELF),
TOKENT("struct", TOK_RWORD_STRUCT),
TOKENT("super", TOK_RWORD_SUPER),
TOKENT("true", TOK_RWORD_TRUE),
@@ -416,7 +416,6 @@ const char* Token::typestr(enum eTokenType type) case TOK_INTEGER: return "TOK_INTEGER";
case TOK_CHAR: return "TOK_CHAR";
case TOK_FLOAT: return "TOK_FLOAT";
- case TOK_UNDERSCORE: return "TOK_UNDERSCORE";
case TOK_CATTR_OPEN: return "TOK_CATTR_OPEN";
case TOK_ATTR_OPEN: return "TOK_ATTR_OPEN";
@@ -542,3 +541,50 @@ const char* Token::typestr(enum eTokenType type) return os;
}
+TokenTree::TokenTree(Token tok)
+{
+
+}
+TokenTree::TokenTree(::std::vector<TokenTree> subtrees)
+{
+
+}
+
+TTStream::TTStream(const TokenTree& input_tt):
+ m_input_tt(input_tt),
+ m_cur_layer(&input_tt)
+{
+}
+TTStream::~TTStream()
+{
+}
+Token TTStream::realGetToken()
+{
+ return Token(TOK_EOF);
+}
+
+TokenStream::TokenStream():
+ m_cache_valid(false)
+{
+}
+TokenStream::~TokenStream()
+{
+}
+
+Token TokenStream::getToken()
+{
+ if( m_cache_valid )
+ {
+ m_cache_valid = false;
+ return m_cache;
+ }
+ else
+ {
+ return this->realGetToken();
+ }
+}
+void TokenStream::putback(Token tok)
+{
+ m_cache_valid = true;
+ m_cache = tok;
+}
diff --git a/parse/lex.hpp b/parse/lex.hpp index a219ae94..88aef072 100644 --- a/parse/lex.hpp +++ b/parse/lex.hpp @@ -20,7 +20,6 @@ enum eTokenType TOK_INTEGER,
TOK_CHAR,
TOK_FLOAT,
- TOK_UNDERSCORE,
TOK_CATTR_OPEN,
TOK_ATTR_OPEN,
@@ -154,11 +153,11 @@ public: Token(uint64_t val, enum eCoreType datatype);
Token(double val, enum eCoreType datatype);
- enum eTokenType type() { return m_type; }
- const ::std::string& str() { return m_str; }
- enum eCoreType datatype() { return m_datatype; }
- uint64_t intval() { return m_intval; }
- double floatval() { return m_floatval; }
+ enum eTokenType type() const { return m_type; }
+ const ::std::string& str() const { return m_str; }
+ enum eCoreType datatype() const { return m_datatype; }
+ uint64_t intval() const { return m_intval; }
+ double floatval() const { return m_floatval; }
static const char* typestr(enum eTokenType type);
};
@@ -167,9 +166,15 @@ extern ::std::ostream& operator<<(::std::ostream& os, Token& tok); class TokenStream
{
+ bool m_cache_valid;
+ Token m_cache;
public:
- virtual Token getToken() = 0;
- virtual void putback(Token tok) = 0;
+ TokenStream();
+ virtual ~TokenStream();
+ Token getToken();
+ void putback(Token tok);
+protected:
+ virtual Token realGetToken() = 0;
};
class Lexer
@@ -192,4 +197,25 @@ private: class EndOfFile {};
};
+class TokenTree
+{
+public:
+ TokenTree(Token tok);
+ TokenTree(::std::vector<TokenTree> subtrees);
+};
+
+class TTStream:
+ public TokenStream
+{
+ const TokenTree& m_input_tt;
+ const TokenTree* m_cur_layer;
+ ::std::vector<unsigned int> m_index_stack;
+public:
+ TTStream(const TokenTree& input_tt);
+ ~TTStream();
+
+protected:
+ virtual Token realGetToken();
+};
+
#endif // LEX_HPP_INCLUDED
diff --git a/parse/parseerror.cpp b/parse/parseerror.cpp index 044847e7..37beb863 100644 --- a/parse/parseerror.cpp +++ b/parse/parseerror.cpp @@ -7,6 +7,18 @@ ParseError::Base::~Base() throw() {
}
+ParseError::Generic::Generic(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "Generic(" << message << ")" << ::std::endl;
+}
+
+ParseError::BugCheck::BugCheck(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "BugCheck(" << message << ")" << ::std::endl;
+}
+
ParseError::Todo::Todo(::std::string message):
m_message(message)
{
diff --git a/parse/parseerror.hpp b/parse/parseerror.hpp index b708565d..11324476 100644 --- a/parse/parseerror.hpp +++ b/parse/parseerror.hpp @@ -13,6 +13,24 @@ public: virtual ~Base() throw();
};
+class Generic:
+ public Base
+{
+ ::std::string m_message;
+public:
+ Generic(::std::string message);
+ virtual ~Generic() throw () {}
+};
+
+class BugCheck:
+ public Base
+{
+ ::std::string m_message;
+public:
+ BugCheck(::std::string message);
+ virtual ~BugCheck() throw () {}
+};
+
class Todo:
public Base
{
diff --git a/parse/preproc.cpp b/parse/preproc.cpp index fa051a3e..2287c41e 100644 --- a/parse/preproc.cpp +++ b/parse/preproc.cpp @@ -2,8 +2,7 @@ #include <iostream>
Preproc::Preproc(::std::string path):
- m_lex(path),
- m_cache_valid(false)
+ m_lex(path)
{
//ctor
}
@@ -31,20 +30,7 @@ Token Preproc::getTokenInt() }
}
-Token Preproc::getToken()
+Token Preproc::realGetToken()
{
- if( m_cache_valid )
- {
- m_cache_valid = false;
- return m_cache;
- }
- else
- {
- return this->getTokenInt();
- }
-}
-void Preproc::putback(Token tok)
-{
- m_cache_valid = true;
- m_cache = tok;
+ return getTokenInt();
}
diff --git a/parse/preproc.hpp b/parse/preproc.hpp index 827ce249..bedb3076 100644 --- a/parse/preproc.hpp +++ b/parse/preproc.hpp @@ -8,15 +8,11 @@ class Preproc: {
Lexer m_lex;
- bool m_cache_valid;
- Token m_cache;
-
public:
Preproc(::std::string path);
~Preproc();
- virtual Token getToken();
- virtual void putback(Token tok);
+ virtual Token realGetToken();
private:
Token getTokenInt();
};
diff --git a/parse/root.cpp b/parse/root.cpp index c82527a2..2dac321a 100644 --- a/parse/root.cpp +++ b/parse/root.cpp @@ -232,6 +232,8 @@ void Parse_TypeConds(TokenStream& lex, AST::TypeParams& params) /// Parse a function definition (after the 'fn')
AST::Function Parse_FunctionDef(TokenStream& lex)
{
+ TRACE_FUNCTION;
+
Token tok;
// Name
@@ -254,12 +256,45 @@ AST::Function Parse_FunctionDef(TokenStream& lex) else {
lex.putback(tok);
}
+
+ AST::Function::Class fcn_class = AST::Function::CLASS_UNBOUND;
GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_AMP )
+ {
+ // By-reference method
+ if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ {
+ throw ParseError::Todo("Lifetimes on self in methods");
+ }
+ if( tok.type() == TOK_RWORD_MUT )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
+ fcn_class = AST::Function::CLASS_MUTMETHOD;
+ }
+ else
+ {
+ CHECK_TOK(tok, TOK_RWORD_SELF);
+ fcn_class = AST::Function::CLASS_REFMETHOD;
+ }
+ GET_TOK(tok, lex);
+ }
+ else if( tok.type() == TOK_RWORD_SELF )
+ {
+ // By-value method
+ fcn_class = AST::Function::CLASS_VALMETHOD;
+ GET_TOK(tok, lex);
+ throw ParseError::Todo("By-value methods");
+ }
+ else
+ {
+ // Unbound method
+ }
::std::vector<AST::StructItem> args;
- if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE )
+ if( tok.type() != TOK_PAREN_CLOSE )
{
- // Argument list
lex.putback(tok);
+ // Argument list
do {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
@@ -287,7 +322,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex) AST::Expr code = Parse_ExprBlock(lex);
- return AST::Function(name, params, ret_type, args, code);
+ return AST::Function(name, params, fcn_class, ret_type, args, code);
}
AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex)
diff --git a/parse/tokentree.hpp b/parse/tokentree.hpp new file mode 100644 index 00000000..52871cce --- /dev/null +++ b/parse/tokentree.hpp @@ -0,0 +1,10 @@ +#ifndef TOKENTREE_HPP_INCLUDED
+#define TOKENTREE_HPP_INCLUDED
+
+#include "lex.hpp"
+
+
+extern TokenTree Parse_TT(TokenStream& lex);
+extern TokenTree Parse_TT_Expr(TokenStream& lex);
+
+#endif // TOKENTREE_HPP_INCLUDED
|