diff options
author | John Hodge (bugs) <tpg@mutabah.net> | 2014-12-07 18:53:17 +0800 |
---|---|---|
committer | John Hodge (bugs) <tpg@mutabah.net> | 2014-12-07 18:53:17 +0800 |
commit | 0bfd3352489411a1e1d6b98397979ad91e2a52b1 (patch) | |
tree | c3e41ae23991f4b95ad155e7601f6f5a5c36aa64 | |
parent | 6178198e6a5f0ff2384660253347b6e9b5d686e2 (diff) | |
download | mrust-0bfd3352489411a1e1d6b98397979ad91e2a52b1.tar.gz |
Macro expansion working, onwards to field parsing
-rw-r--r-- | macros.cpp | 36 | ||||
-rw-r--r-- | macros.hpp | 35 | ||||
-rw-r--r-- | parse/expr.cpp | 24 | ||||
-rw-r--r-- | parse/lex.cpp | 35 | ||||
-rw-r--r-- | parse/lex.hpp | 28 |
5 files changed, 123 insertions, 35 deletions
@@ -65,14 +65,17 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) // 4. Return expander
FOREACH(MacroRules, rule_it, rules)
{
+ Token tok;
// Create token stream for input tree
TTStream lex(input);
- ::std::map<const char*,TokenTree> bound_tts;
+ if(GET_TOK(tok, lex) == TOK_EOF) {
+ throw ParseError::Unexpected(tok);
+ }
+ ::std::map<const char*,TokenTree,cmp_str> bound_tts;
// Parse according to rules
bool fail = false;
FOREACH(::std::vector<MacroPatEnt>, pat_it, rule_it->m_pattern)
{
- Token tok;
TokenTree val;
const MacroPatEnt& pat = *pat_it;
try
@@ -99,9 +102,13 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) break;
}
}
+ // TODO: Actually check if the final token is the closer to the first
+ if( !fail && GET_TOK(tok, lex) == TOK_EOF) {
+ throw ParseError::Unexpected(tok);
+ }
if( !fail && lex.getToken().type() == TOK_EOF )
{
- throw ParseError::Todo("Macro expansions");
+ return MacroExpander(rule_it->m_contents, bound_tts);
}
}
throw ParseError::Todo("Error when macro fails to match");
@@ -112,5 +119,26 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) Token MacroExpander::realGetToken()
{
- throw ParseError::Todo("MacroExpander");
+ if( m_ttstream.get() )
+ {
+ Token rv = m_ttstream->getToken();
+ if( rv.type() != TOK_EOF )
+ return rv;
+ m_ttstream.reset();
+ }
+ if( m_ofs < m_contents.size() )
+ {
+ const MacroRuleEnt& ent = m_contents[m_ofs];
+ m_ofs ++;
+ if( ent.name.size() != 0 ) {
+ // Binding!
+ m_ttstream.reset( new TTStream(m_mappings.at(ent.name.c_str())) );
+ return m_ttstream->getToken();
+ }
+ else {
+ return ent.tok;
+ }
+ throw ParseError::Todo("MacroExpander - realGetToken");
+ }
+ return Token(TOK_EOF);
}
@@ -3,9 +3,15 @@ #include "parse/lex.hpp"
#include <map>
+#include <memory>
+#include <cstring>
+
+class MacroExpander;
class MacroRuleEnt
{
+ friend class MacroExpander;
+
Token tok;
::std::string name;
public:
@@ -44,11 +50,6 @@ struct MacroPatEnt /// A rule within a macro_rules! blcok
class MacroRule
{
- struct MacroRuleState
- {
- ::std::map< ::std::string, TokenTree> m_mappings;
- size_t ofs;
- };
public:
::std::vector<MacroPatEnt> m_pattern;
::std::vector<MacroRuleEnt> m_contents;
@@ -57,10 +58,34 @@ public: /// A sigle 'macro_rules!' block
typedef ::std::vector<MacroRule> MacroRules;
+struct cmp_str {
+ bool operator()(const char* a, const char* b) const {
+ return ::std::strcmp(a, b) < 0;
+ }
+};
+
class MacroExpander:
public TokenStream
{
+ typedef ::std::map<const char*, TokenTree, cmp_str> t_mappings;
+ const t_mappings m_mappings;
+ const ::std::vector<MacroRuleEnt>& m_contents;
+ size_t m_ofs;
+
+ ::std::auto_ptr<TTStream> m_ttstream;
public:
+ MacroExpander(const MacroExpander& x):
+ m_mappings(x.m_mappings),
+ m_contents(x.m_contents),
+ m_ofs(0)
+ {
+ }
+ MacroExpander(const ::std::vector<MacroRuleEnt>& contents, t_mappings mappings):
+ m_mappings(mappings),
+ m_contents(contents),
+ m_ofs(0)
+ {
+ }
virtual Token realGetToken();
};
diff --git a/parse/expr.cpp b/parse/expr.cpp index b3c00247..22f774bb 100644 --- a/parse/expr.cpp +++ b/parse/expr.cpp @@ -406,6 +406,11 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex) return ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype());
case TOK_FLOAT:
throw ParseError::Todo("Float");
+ case TOK_RWORD_SELF: {
+ AST::Path path;
+ path.append( AST::PathNode("self", ::std::vector<TypeRef>()) );
+ return ExprNode(ExprNode::TagNamedValue(), path);
+ }
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));
@@ -477,6 +482,8 @@ TokenTree Parse_TT_Val(TokenStream& lex) return inner;
}
break; }
+ case TOK_RWORD_SELF:
+ return TokenTree(tok);
case TOK_RWORD_MATCH:
ret.push_back(TokenTree(tok));
ret.push_back(Parse_TT(lex));
@@ -516,6 +523,23 @@ TokenTree Parse_TT_Expr(TokenStream& lex) ret.push_back(tok);
ret.push_back(Parse_TT_Val(lex));
break;
+ case TOK_DOT:
+ ret.push_back(tok);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ret.push_back(tok);
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_DOUBLE_COLON:
+ throw ParseError::Todo("Generic type params in TT expr");
+ case TOK_PAREN_OPEN:
+ lex.putback(tok);
+ ret.push_back(Parse_TT(lex));
+ break;
+ default:
+ lex.putback(tok);
+ break;
+ }
+ break;
default:
lex.putback(tok);
cont = false;
diff --git a/parse/lex.cpp b/parse/lex.cpp index e48cb9bb..4c1103a1 100644 --- a/parse/lex.cpp +++ b/parse/lex.cpp @@ -10,6 +10,7 @@ #include <cassert>
#include <iostream>
#include <cstdlib> // strtol
+#include <typeinfo>
Lexer::Lexer(::std::string filename):
m_istream(filename.c_str()),
@@ -225,7 +226,6 @@ Token Lexer::getToken() str.push_back(ch);
ch = this->getc();
}
- this->putback();
if( ch == '!' )
{
@@ -233,6 +233,7 @@ Token Lexer::getToken() }
else
{
+ this->putback();
for( unsigned int i = 0; i < LEN(RWORDS); i ++ )
{
if( str < RWORDS[i].chars ) break;
@@ -541,19 +542,6 @@ const char* Token::typestr(enum eTokenType type) return os;
}
-TokenTree::TokenTree()
-{
-
-}
-TokenTree::TokenTree(Token tok)
-{
-
-}
-TokenTree::TokenTree(::std::vector<TokenTree> subtrees)
-{
-
-}
-
TTStream::TTStream(const TokenTree& input_tt):
m_input_tt(input_tt)
{
@@ -569,14 +557,21 @@ Token TTStream::realGetToken() // If current index is above TT size, go up
unsigned int& idx = m_stack.back().first;
const TokenTree& tree = *m_stack.back().second;
+
+ if(idx == 0 && tree.size() == 0) {
+ idx ++;
+ return tree.tok();
+ }
+
if(idx < tree.size())
{
- if( tree[idx].size() == 0 ) {
- idx ++;
- return tree[idx-1].tok();
+ const TokenTree& subtree = tree[idx];
+ idx ++;
+ if( subtree.size() == 0 ) {
+ return subtree.tok();
}
else {
- m_stack.push_back( ::std::make_pair(0, &tree[idx] ) );
+ m_stack.push_back( ::std::make_pair(0, &subtree ) );
}
}
else {
@@ -603,7 +598,9 @@ Token TokenStream::getToken() }
else
{
- return this->realGetToken();
+ Token ret = this->realGetToken();
+ ::std::cout << "getToken[" << typeid(*this).name() << "] - " << ret << ::std::endl;
+ return ret;
}
}
void TokenStream::putback(Token tok)
diff --git a/parse/lex.hpp b/parse/lex.hpp index e01a1cbf..dbf365a0 100644 --- a/parse/lex.hpp +++ b/parse/lex.hpp @@ -199,14 +199,28 @@ private: class TokenTree
{
+ Token m_tok;
+ ::std::vector<TokenTree> m_subtrees;
public:
- TokenTree();
- TokenTree(Token tok);
- TokenTree(::std::vector<TokenTree> subtrees);
-
- const unsigned int size() const;
- const TokenTree& operator[](unsigned int) const;
- const Token& tok() const;
+ TokenTree() {}
+ TokenTree(Token tok):
+ m_tok(tok)
+ {
+ }
+ TokenTree(::std::vector<TokenTree> subtrees):
+ m_subtrees(subtrees)
+ {
+ }
+
+ const unsigned int size() const {
+ return m_subtrees.size();
+ }
+ const TokenTree& operator[](unsigned int idx) const {
+ return m_subtrees[idx];
+ }
+ const Token& tok() const {
+ return m_tok;
+ }
};
class TTStream:
|