diff options
-rw-r--r-- | src/ast/ast.cpp | 48 | ||||
-rw-r--r-- | src/ast/ast.hpp | 80 | ||||
-rw-r--r-- | src/ast/ast_expr.hpp | 14 | ||||
-rw-r--r-- | src/ast/path.hpp | 27 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 96 | ||||
-rw-r--r-- | src/macros.hpp | 1 | ||||
-rw-r--r-- | src/parse/expr.cpp | 6 | ||||
-rw-r--r-- | src/parse/lex.cpp | 1 | ||||
-rw-r--r-- | src/parse/lex.hpp | 39 | ||||
-rw-r--r-- | src/parse/root.cpp | 141 | ||||
-rw-r--r-- | src/parse/tokentree.hpp | 39 |
11 files changed, 406 insertions, 86 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index e1e6e877..7d151063 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -22,23 +22,49 @@ const ::std::vector<TypeRef>& PathNode::args() const return m_params;
}
+Path& Path::operator+=(const Path& other)
+{
+ for(auto& node : other.m_nodes)
+ append(node);
+ return *this;
+}
+::std::ostream& operator<<(::std::ostream& os, const Path& path)
+{
+ switch(path.m_class)
+ {
+ case Path::RELATIVE:
+ os << "Path({" << path.m_nodes << "})";
+ break;
+ case Path::ABSOLUTE:
+ os << "Path(TagAbsolute, {" << path.m_nodes << "})";
+ break;
+ case Path::LOCAL:
+ os << "Path(TagLocal, " << path.m_nodes[0].name() << ")";
+ break;
+ }
+ return os;
+}
+
::std::ostream& operator<<(::std::ostream& os, const Pattern& pat)
{
switch(pat.m_class)
{
+ case Pattern::ANY:
+ os << "Pattern(TagWildcard, '" << pat.m_binding << "' @ _)";
+ break;
case Pattern::MAYBE_BIND:
- os << "Pattern(TagMaybeBind, '" << pat.m_path[0].name() << "')";
+ os << "Pattern(TagMaybeBind, '" << pat.m_binding << "')";
break;
case Pattern::VALUE:
//os << "Pattern(TagValue, " << *pat.m_node << ")";
- os << "Pattern(TagValue, TODO:ExprNode)";
+ os << "Pattern(TagValue, '" << pat.m_binding << "' @ TODO:ExprNode)";
break;
case Pattern::TUPLE:
- os << "Pattern(TagTuple, " << pat.m_sub_patterns << ")";
+ os << "Pattern(TagTuple, '" << pat.m_binding << "' @ [" << pat.m_sub_patterns << "])";
break;
case Pattern::TUPLE_STRUCT:
- os << "Pattern(TagEnumVariant, " << pat.m_path << ", " << pat.m_sub_patterns << ")";
+ os << "Pattern(TagEnumVariant, '" << pat.m_binding << "' @ " << pat.m_path << ", [" << pat.m_sub_patterns << "])";
break;
}
return os;
@@ -52,11 +78,25 @@ void Impl::add_function(bool is_public, Function fcn) {
}
+Crate::Crate():
+ m_root_module(*this, ""),
+ m_load_std(true)
+{
+}
void Crate::iterate_functions(fcn_visitor_t* visitor)
{
m_root_module.iterate_functions(visitor, *this);
}
+void Module::add_ext_crate(::std::string ext_name, ::std::string int_name)
+{
+ DEBUG("add_ext_crate(\"" << ext_name << "\" as " << int_name << ")");
+ if( ext_name == "std" )
+ {
+ // HACK! Load std using a hackjob (included within the compiler)
+ }
+ throw ParseError::Todo("'extern crate'");
+}
void Module::add_constant(bool is_public, ::std::string name, TypeRef type, Expr val)
{
::std::cout << "add_constant()" << ::std::endl;
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 6c3e726c..0b124ad7 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -7,6 +7,7 @@ #include "../coretypes.hpp"
#include <memory>
+#include "../parse/tokentree.hpp"
#include "../types.hpp"
namespace AST {
@@ -31,29 +32,43 @@ public: m_items(items)
{
}
+
+ const ::std::string& name() const { return m_name; }
};
class ExprNode;
class Pattern
{
+public:
enum BindType {
MAYBE_BIND,
+ ANY,
VALUE,
TUPLE,
TUPLE_STRUCT,
};
+private:
BindType m_class;
+ ::std::string m_binding;
Path m_path;
unique_ptr<ExprNode> m_node;
::std::vector<Pattern> m_sub_patterns;
public:
- Pattern();
+ Pattern():
+ m_class(ANY)
+ {}
+
+ struct TagBind {};
+ Pattern(TagBind, ::std::string name):
+ m_class(ANY),
+ m_binding(name)
+ {}
struct TagMaybeBind {};
Pattern(TagMaybeBind, ::std::string name):
m_class(MAYBE_BIND),
- m_path(Path::TagLocal(), name)
+ m_binding(name)
{}
struct TagValue {};
@@ -74,6 +89,21 @@ public: m_path( ::std::move(path) ),
m_sub_patterns( ::std::move(sub_patterns) )
{}
+
+ // Mutators
+ void set_bind(::std::string name) {
+ m_binding = name;
+ }
+
+ // Accessors
+ const ::std::string& binding() const { return m_binding; }
+ BindType type() const { return m_class; }
+ ExprNode& node() { return *m_node; }
+ const ExprNode& node() const { return *m_node; }
+ Path& path() { return m_path; }
+ const Path& path() const { return m_path; }
+ ::std::vector<Pattern>& sub_patterns() { return m_sub_patterns; }
+ const ::std::vector<Pattern>& sub_patterns() const { return m_sub_patterns; }
friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat);
};
@@ -152,33 +182,65 @@ public: };
+class Crate;
class Module;
typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Function& fcn);
class Module
{
- ::std::vector< ::std::pair<Function,bool> > m_functions;
+ typedef ::std::vector< ::std::pair<Function, bool> > itemlist_fcn_t;
+ typedef ::std::vector< ::std::pair<Module, bool> > itemlist_mod_t;
+ typedef ::std::vector< ::std::tuple< ::std::string, Path, bool > > itemlist_use_t;
+
+ const Crate& m_crate;
+ ::std::string m_name;
+ ::std::vector<MetaItem> m_attrs;
+ itemlist_fcn_t m_functions;
+ itemlist_mod_t m_submods;
+ itemlist_use_t m_imports;
public:
- void add_alias(bool is_public, Path path) {}
+ Module(const Crate& crate, ::std::string name):
+ m_crate(crate),
+ m_name(name)
+ {
+ }
+ void add_ext_crate(::std::string ext_name, ::std::string imp_name);
+ void add_alias(bool is_public, Path path, ::std::string name) {
+ m_imports.push_back( ::std::make_tuple(name, path, is_public) );
+ }
void add_constant(bool is_public, ::std::string name, TypeRef type, Expr val);
void add_global(bool is_public, bool is_mut, ::std::string name, TypeRef type, Expr val);
void add_struct(bool is_public, ::std::string name, TypeParams params, ::std::vector<StructItem> items);
void add_function(bool is_public, Function func);
void add_impl(Impl impl);
+ void add_attr(MetaItem item) {
+ m_attrs.push_back(item);
+ }
+
void iterate_functions(fcn_visitor_t* visitor, const Crate& crate);
+
+ const Crate& crate() const { return m_crate; }
+
+ const ::std::string& name() const { return m_name; }
+
+ const ::std::vector<MetaItem>& attrs() const { return m_attrs; }
+ const itemlist_fcn_t& functions() const { return m_functions; }
+ const itemlist_mod_t& submods() const { return m_submods; }
+ const itemlist_use_t& imports() const { return m_imports; }
};
class Crate
{
- Module m_root_module;
public:
- Crate(Module root_module):
- m_root_module(root_module)
- {
- }
+ Module m_root_module;
+ bool m_load_std;
+
+ Crate();
+ Module& root_module() { return m_root_module; }
+
void iterate_functions( fcn_visitor_t* visitor );
};
diff --git a/src/ast/ast_expr.hpp b/src/ast/ast_expr.hpp index 223d7a4d..1b0a876d 100644 --- a/src/ast/ast_expr.hpp +++ b/src/ast/ast_expr.hpp @@ -28,6 +28,20 @@ struct ExprNode_Block: virtual void visit(NodeVisitor& nv) override; }; +struct ExprNode_Macro: + public ExprNode +{ + ::std::string m_name; + ::TokenTree m_tokens; + + ExprNode_Macro(::std::string name, ::TokenTree&& tokens): + m_name(name), + m_tokens( move(tokens) ) + {} + + virtual void visit(NodeVisitor& nv) override; +}; + // Return a value struct ExprNode_Return: public ExprNode diff --git a/src/ast/path.hpp b/src/ast/path.hpp index bc33c318..9887d192 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -66,6 +66,17 @@ public: m_class(LOCAL), m_nodes({PathNode(name, {})}) {} + + static Path add_tailing(const Path& a, const Path& b) { + Path ret(a); + for(const auto& ent : b.m_nodes) + ret.m_nodes.push_back(ent); + return ret; + } + Path operator+(const Path& x) const { + return Path(*this) += x; + } + Path& operator+=(const Path& x); void append(PathNode node) { m_nodes.push_back(node); @@ -79,21 +90,7 @@ public: PathNode& operator[](size_t idx) { return m_nodes[idx]; } const PathNode& operator[](size_t idx) const { return m_nodes[idx]; } - friend ::std::ostream& operator<<(::std::ostream& os, const Path& path) { - switch(path.m_class) - { - case RELATIVE: - os << "Path({" << path.m_nodes << "})"; - break; - case ABSOLUTE: - os << "Path(TagAbsolute, {" << path.m_nodes << "})"; - break; - case LOCAL: - os << "Path(TagLocal, " << path.m_nodes[0].name() << ")"; - break; - } - return os; - } + friend ::std::ostream& operator<<(::std::ostream& os, const Path& path); }; } // namespace AST diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 504fec93..e1dea29f 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -1,4 +1,9 @@ /*
+ * "mrustc" Rust->C converter
+ * - By John Hodge (Mutabah / thePowersGang)
+ *
+ * convert/resolve.cpp
+ * - Resolve names into absolute format
*/
#include "../common.hpp"
#include "../ast/ast.hpp"
@@ -8,6 +13,7 @@ class CPathResolver {
const AST::Crate& m_crate;
const AST::Module& m_module;
+ const AST::Path m_module_path;
::std::vector< ::std::string > m_locals;
// TODO: Maintain a stack of variable scopes
@@ -47,12 +53,20 @@ public: {
}
+ void visit(AST::ExprNode_Macro& node) {
+ throw ParseError::Todo("Resolve-time expanding of macros");
+
+ //MacroExpander expanded_macro = Macro_Invoke(node.m_name.c_str(), node.m_tokens);
+ // TODO: Requires being able to replace the node with a completely different type of node
+ //node.replace( Parse_Expr0(expanded_macro) );
+ }
+
void visit(AST::ExprNode_NamedValue& node) {
m_res.resolve_path(node.m_path, true);
}
- void visit(AST::ExprNode_Match& node) {
-
+ void visit(AST::ExprNode_Match& node)
+ {
AST::NodeVisitor::visit(node.m_val);
for( auto& arm : node.m_arms )
@@ -110,6 +124,33 @@ void CPathResolver::resolve_path(AST::Path& path, bool allow_variables) const }
}
// Search relative to current module
+ // > Search local use definitions (function-level)
+ // - TODO: Local use statements (scoped)
+ // > Search module-level definitions
+ for( const auto& item_mod : m_module.submods() )
+ {
+ if( item_mod.first.name() == path[0].name() ) {
+ // Check name down?
+ // Add current module path
+ path = m_module_path + path;
+ }
+ }
+ for( const auto& item_fcn : m_module.functions() )
+ {
+ if( item_fcn.first.name() == path[0].name() ) {
+ path = m_module_path + path;
+ break;
+ }
+ }
+ for( const auto& import : m_module.imports() )
+ {
+ const ::std::string& bind_name = ::std::get<0>(import);
+ const AST::Path& bind_path = ::std::get<1>(import);
+ if( bind_name == path[0].name() ) {
+ path = AST::Path::add_tailing(bind_path, path);
+ }
+ }
+
throw ParseError::Todo("CPathResolver::resolve_path()");
}
}
@@ -117,15 +158,66 @@ void CPathResolver::resolve_path(AST::Path& path, bool allow_variables) const void CPathResolver::resolve_type(TypeRef& type) const
{
// TODO: Convert type into absolute
+ DEBUG("type = " << type);
throw ParseError::Todo("CPathResolver::resolve_type()");
}
void CPathResolver::handle_pattern(AST::Pattern& pat)
{
DEBUG("pat = " << pat);
+ // Resolve names
+ switch(pat.type())
+ {
+ case AST::Pattern::ANY:
+ // Wildcard, nothing to do
+ break;
+ case AST::Pattern::MAYBE_BIND: {
+ ::std::string name = pat.binding();
+ // Locate a _constant_ within the current namespace which matches this name
+ // - Variables don't count
+ AST::Path newpath;
+ newpath.append( AST::PathNode(name, {}) );
+ resolve_path(newpath, false);
+ if( newpath.is_relative() )
+ {
+ // It's a name binding (desugar to 'name @ _')
+ pat = AST::Pattern();
+ pat.set_bind(name);
+ }
+ else
+ {
+ // It's a constant (value)
+
+ pat = AST::Pattern(
+ AST::Pattern::TagValue(),
+ ::std::unique_ptr<AST::ExprNode>( new AST::ExprNode_NamedValue( ::std::move(newpath) ) )
+ );
+ }
+ break; }
+ case AST::Pattern::VALUE: {
+ CResolvePaths_NodeVisitor nv(*this);
+ pat.node().visit(nv);
+ break; }
+ case AST::Pattern::TUPLE:
+ // Tuple is handled by subpattern code
+ break;
+ case AST::Pattern::TUPLE_STRUCT:
+ // Resolve the path!
+ // - TODO: Restrict to types and enum variants
+ resolve_path( pat.path(), false );
+ break;
+ }
+ // Extract bindings and add to namespace
+ if( pat.binding().size() > 0 )
+ m_locals.push_back( pat.binding() );
+ for( auto& subpat : pat.sub_patterns() )
+ handle_pattern(subpat);
+
+
throw ParseError::Todo("CPathResolver::handle_pattern()");
}
+/// Perform name resolution in a function
void CPathResolver::handle_function(AST::Function& fcn)
{
CResolvePaths_NodeVisitor node_visitor(*this);
diff --git a/src/macros.hpp b/src/macros.hpp index 2618825b..f5779d4d 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -2,6 +2,7 @@ #define MACROS_HPP_INCLUDED
#include "parse/lex.hpp"
+#include "parse/tokentree.hpp"
#include <map>
#include <memory>
#include <cstring>
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index c56c529d..fd6f14b8 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -483,10 +483,10 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) ExprNodeP rv = Parse_Expr0(lex);
GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
return rv; }
- case TOK_MACRO: {
- // Need to create a token tree, pass to the macro, then pass the result of that to Parse_Expr0
+ case TOK_MACRO:
+ //return NEWNODE( AST::ExprNode_Macro, tok.str(), Parse_TT(lex) );
+ {
MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), Parse_TT(lex));
-
return Parse_Expr0(expanded_macro);
}
default:
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 79db4603..f893f26c 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -6,6 +6,7 @@ * \brief Low-level lexer
*/
#include "lex.hpp"
+#include "tokentree.hpp"
#include "parseerror.hpp"
#include <cassert>
#include <iostream>
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index dbf365a0..6a798909 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -197,43 +197,4 @@ private: class EndOfFile {};
};
-class TokenTree
-{
- Token m_tok;
- ::std::vector<TokenTree> m_subtrees;
-public:
- 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:
- public TokenStream
-{
- const TokenTree& m_input_tt;
- ::std::vector< ::std::pair<unsigned int, const TokenTree*> > m_stack;
-public:
- TTStream(const TokenTree& input_tt);
- ~TTStream();
-
-protected:
- virtual Token realGetToken();
-};
-
#endif // LEX_HPP_INCLUDED
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 4f2a5084..e922b39f 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -481,11 +481,88 @@ AST::Impl Parse_Impl(TokenStream& lex) return impl;
}
-AST::Module Parse_ModRoot(const ::std::string& path, Preproc& lex)
+void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function<void(AST::Path, ::std::string)> fcn)
+{
+ throw ParseError::Todo("Wildcard imports");
+}
+
+void Parse_Use(Preproc& lex, ::std::function<void(AST::Path, ::std::string)> fcn)
{
Token tok;
+ AST::Path path = AST::Path( AST::Path::TagAbsolute() );
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_SELF:
+ throw ParseError::Todo("Parse_Use - self");
+ break;
+ case TOK_RWORD_SUPER:
+ throw ParseError::Todo("Parse_Use - super");
+ break;
+ case TOK_IDENT:
+ path.append( AST::PathNode(tok.str(), {}) );
+ break;
+ default:
+ throw ParseError::Unexpected(tok);
+ }
+ // TODO: Use from crate root
+ while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
+ {
+ if( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ path.append( AST::PathNode(tok.str(), {}) );
+ }
+ else
+ {
+ switch( tok.type() )
+ {
+ case TOK_BRACE_OPEN:
+ throw ParseError::Todo("Parse_Use - multiples");
+ break;
+ case TOK_STAR:
+ throw ParseError::Todo("Parse_Use - wildcard/glob");
+ break;
+ default:
+ throw ParseError::Unexpected(tok);
+ }
+ GET_TOK(tok, lex);
+ break;
+ }
+ }
+
+ ::std::string name;
+ // TODO: This should only be allowed if the last token was an ident
+ if( tok.type() == TOK_RWORD_AS )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = tok.str();
+ }
+ else
+ {
+ lex.putback(tok);
+ name = path[path.size()-1].name();
+ }
+
+ fcn(path, name);
+}
- AST::Module mod;
+void Parse_ModRoot(Preproc& lex, AST::Module& mod, const ::std::string& path)
+{
+ const bool nested_module = (path.size() == 0); // 'mod name { code }', as opposed to 'mod name;'
+ Token tok;
+
+ if( mod.crate().m_load_std )
+ {
+ // Import the prelude
+ AST::Path prelude_path = AST::Path(AST::Path::TagAbsolute());
+ prelude_path.append( AST::PathNode("std", {}) );
+ prelude_path.append( AST::PathNode("prelude", {}) );
+ Parse_Use_Wildcard(prelude_path,
+ [&mod](AST::Path p, std::string s) {
+ mod.add_alias(false, p, s);
+ }
+ );
+ }
// Attributes on module/crate (will continue loop)
while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
@@ -493,26 +570,25 @@ AST::Module Parse_ModRoot(const ::std::string& path, Preproc& lex) AST::MetaItem item = Parse_MetaItem(lex);
GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- throw ParseError::Todo("Parent attrs");
- //mod_attrs.push_back( item );
+ mod.add_attr( item );
}
lex.putback(tok);
- // TODO: Handle known parent attribs if operating on crate root
-
+ // TODO: Iterate attributes, and check for handlers on each
+
for(;;)
{
// Check 1 - End of module (either via a closing brace, or EOF)
switch(GET_TOK(tok, lex))
{
case TOK_BRACE_CLOSE:
- if( path.size() > 0 )
+ if( !nested_module )
throw ParseError::Unexpected(tok);
- return mod;
+ return ;
case TOK_EOF:
- if( path.size() == 0 )
+ if( nested_module )
throw ParseError::Unexpected(tok);
- return mod;
+ return ;
default:
lex.putback(tok);
break;
@@ -542,8 +618,7 @@ AST::Module Parse_ModRoot(const ::std::string& path, Preproc& lex) switch( GET_TOK(tok, lex) )
{
case TOK_RWORD_USE:
- // TODO: Do manual path parsing here, as use has its own special set of quirks
- mod.add_alias( is_public, Parse_Path(lex, true, PATH_GENERIC_NONE) );
+ Parse_Use(lex, [&mod,is_public](AST::Path p, std::string s) { mod.add_alias(is_public, p, s); });
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break;
@@ -604,6 +679,44 @@ AST::Module Parse_ModRoot(const ::std::string& path, Preproc& lex) AST::Crate Parse_Crate(::std::string mainfile)
{
- Preproc lex(mainfile);
- return AST::Crate( Parse_ModRoot(mainfile, lex) );
+ Token tok;
+
+ Preproc lex(mainfile);
+ AST::Crate crate;
+ AST::Module& rootmod = crate.root_module();
+
+ // Attributes on module/crate
+ while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
+ {
+ AST::MetaItem item = Parse_MetaItem(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+
+ rootmod.add_attr( item );
+ }
+ lex.putback(tok);
+
+ // Check for crate attributes
+ for( const auto& attr : rootmod.attrs() )
+ {
+ if( attr.name() == "no_std" ) {
+ crate.m_load_std = false;
+ }
+ else {
+ // TODO:
+ }
+ }
+
+ if( crate.m_load_std )
+ {
+ // Load the standard library (add 'extern crate std;')
+ rootmod.add_ext_crate("std", "std");
+ // Prelude imports are handled in Parse_ModRoot
+ }
+
+ // Include the std if the 'no_std' attribute was absent
+ // - First need to load the std macros, then can import the prelude
+
+ Parse_ModRoot(lex, rootmod, mainfile);
+
+ return crate;
}
diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index 4105897d..b1b353ea 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -4,6 +4,45 @@ #include "lex.hpp"
+class TokenTree
+{
+ Token m_tok;
+ ::std::vector<TokenTree> m_subtrees;
+public:
+ 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:
+ public TokenStream
+{
+ const TokenTree& m_input_tt;
+ ::std::vector< ::std::pair<unsigned int, const TokenTree*> > m_stack;
+public:
+ TTStream(const TokenTree& input_tt);
+ ~TTStream();
+
+protected:
+ virtual Token realGetToken();
+};
+
extern TokenTree Parse_TT(TokenStream& lex);
extern TokenTree Parse_TT_Expr(TokenStream& lex);
extern TokenTree Parse_TT_Stmt(TokenStream& lex);
|