Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Parser/C++/syn/swalker-syntax.cc
    1| // Synopsis C++ Parser: swalker-syntax.cc source file
    2| // Implementation of the SWalker class for things that are more to do with
    3| // syntax highlighting than AST generation, such as translating variable
    4| // references and function calls.
    5| 
    6| // $Id: swalker-syntax.cc,v 1.18 2002/11/17 12:11:44 chalky Exp $
    7| //
    8| // This file is a part of Synopsis.
    9| // Copyright (C) 2000-2002 Stephen Davies
   10| // Copyright (C) 2000, 2001 Stefan Seefeld
   11| //
   12| // Synopsis is free software; you can redistribute it and/or modify it
   13| // under the terms of the GNU General Public License as published by
   14| // the Free Software Foundation; either version 2 of the License, or
   15| // (at your option) any later version.
   16| //
   17| // This program is distributed in the hope that it will be useful,
   18| // but WITHOUT ANY WARRANTY; without even the implied warranty of
   19| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   20| // General Public License for more details.
   21| //
   22| // You should have received a copy of the GNU General Public License
   23| // along with this program; if not, write to the Free Software
   24| // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   25| // 02111-1307, USA.
   26| //
   27| // $Log: swalker-syntax.cc,v $
   28| // Revision 1.18  2002/11/17 12:11:44  chalky
   29| // Reformatted all files with astyle --style=ansi, renamed fakegc.hh
   30| //
   31| // Revision 1.17  2002/10/29 02:39:57  chalky
   32| // Changes to compile with g++-3.2
   33| //
   34| // Revision 1.16  2002/10/20 15:38:10  chalky
   35| // Much improved template support, including Function Templates.
   36| //
   37| // Revision 1.15  2002/01/30 11:53:15  chalky
   38| // Couple bug fixes, some cleaning up.
   39| //
   40| // Revision 1.14  2002/01/28 13:17:24  chalky
   41| // More cleaning up of code. Combined xref into LinkStore. Encoded links file.
   42| //
   43| // Revision 1.13  2002/01/25 14:24:33  chalky
   44| // Start of refactoring and restyling effort.
   45| //
   46| // Revision 1.12  2001/07/29 03:28:04  chalky
   47| // More fixes for directory restructure, and fake_std -f flag for C++ parser.
   48| //
   49| 
   50| // This file contains the methods of SWalker that are mostly concerned with
   51| // syntax highlighting (SXR). Having them in a separate file improves
   52| // compilation time significantly for minor updates.
   53| //
   54| //
   55| // From here on, the Translate* visitor methods are mostly only used when
   56| // storing links, ie: they translate code rather than declarations.
   57| //
   58| 
   59| #include <iostream>
   60| #include <string>
   61| #include <typeinfo>
   62| 
   63| #include <occ/ptree.h>
   64| #include <occ/parse.h>
   65| #undef Scope
   66| 
   67| #include "linkstore.hh"
   68| #include "swalker.hh"
   69| #include "builder.hh"
   70| #include "decoder.hh"
   71| #include "lookup.hh"
   72| #include "dumper.hh"
   73| #include "strace.hh"
   74| #include "type.hh"
   75| #include "ast.hh"
   76| 
   77| Ptree*
   78| SWalker::TranslateReturn(Ptree* spec)
   79| {
   80|     STrace trace("SWalker::TranslateReturn");
   81|     if (!m_links)
   82|         return 0;
   83| 
   84|     // Link 'return' keyword
   85|     m_links->span(spec->First(), "file-keyword");
   86| 
   87|     // Translate the body of the return, if present
   88|     if (spec->Length() == 3)
   89|         Translate(spec->Second());
   90|     return 0;
   91| }
   92| 
   93| Ptree*
   94| SWalker::TranslateInfix(Ptree* node)
   95| {
   96|     STrace trace("SWalker::TranslateInfix");
   97|     // [left op right]
   98|     Translate(node->First());
   99|     Types::Typeleft_type = m_type;
  100|     Translate(node->Third());
  101|     Types::Typeright_type = m_type;
  102|     std::string oper = parse_name(node->Second());
  103|     TypeFormatter tf;
  104|     LOG("BINARY-OPER: " << tf.format(left_type) << " " << oper << " " << tf.format(right_type));
  105|     nodeLOG(node);
  106|     if (!left_type || !right_type)
  107|     {
  108|         m_type = NULL;
  109|         return 0;
  110|     }
  111|     // Lookup an appropriate operator
  112|     AST::Functionfunc = m_lookup->lookupOperator(operleft_typeright_type);
  113|     if (func)
  114|     {
  115|         m_type = func->return_type();
  116|         if (m_links)
  117|             m_links->link(node->Second(), func->declared());
  118|     }
  119|     return 0;
  120| }
  121| 
  122| Ptree*
  123| SWalker::TranslateVariable(Ptree* spec)
  124| {
  125|     // REVISIT: Figure out why this is so long!!!
  126|     STrace trace("SWalker::TranslateVariable");
  127|     if (m_links)
  128|         find_comments(spec);
  129|     try
  130|     {
  131|         Ptreename_spec = spec;
  132|         Types::Namedtype;
  133|         ScopedName scoped_name;
  134|         if (!spec->IsLeaf())
  135|         {
  136|             // Must be a scoped name.. iterate through the scopes
  137|             // stop when spec is at the last name
  138|             //nodeLOG(spec);
  139|             // If first node is '::' then reset m_scope to the global scope
  140|             if (spec->First()->Eq("::"))
  141|             {
  142|                 scoped_name.push_back("");
  143|                 spec = spec->Rest();
  144|             }
  145|             while (spec->Length() > 2)
  146|             {
  147|                 scoped_name.push_back(parse_name(spec->First()));
  148|                 /*
  149|                 if (!type) { throw nodeERROR(spec, "scope '" << parse_name(spec->First()) << "' not found!"); }
  150|                 try { m_scope = Types::declared_cast<AST::Scope>(type); }
  151|                 catch (const Types::wrong_type_cast&) { throw nodeERROR(spec, "scope '"<<parse_name(spec->First())<<"' found but not a scope!"); }
  152|                 // Link the scope name
  153|                 if (m_links) m_links->link(spec->First(), m_scope->declared());
  154|                 */
  155|                 spec = spec->Rest()->Rest();
  156|             }
  157|             spec = spec->First();
  158|             // Check for 'operator >>' type syntax:
  159|             if (!spec->IsLeaf() && spec->Length() == 2 && spec->First()->Eq("operator"))
  160|             {
  161|                 // Name lookup is done based on only the operator type, so
  162|                 // skip the 'operator' node
  163|                 spec = spec->Second();
  164|             }
  165|             scoped_name.push_back(parse_name(spec));
  166|         }
  167|         std::string name = parse_name(spec);
  168|         if (m_postfix_flag == Postfix_Var)
  169|         {
  170|             // Variable lookup. m_type will be the vtype
  171|             /*cout << "m_scope is " << (m_scope ? m_type_formatter->format(m_scope->declared()) : "global") << endl;*/
  172|             if (!scoped_name.empty())
  173|                 type = m_lookup->lookupType(scoped_nametruem_scope);
  174|             else if (m_scope)
  175|                 type = m_lookup->lookupType(namem_scope);
  176|             else
  177|                 type = m_lookup->lookupType(name);
  178|             if (!type)
  179|             {
  180|                 throw nodeERROR(spec, "variable '" << name << "' not found!");
  181|             }
  182|             // Now find vtype (throw wrong_type_cast if not a variable)
  183|             try
  184|             {
  185|                 Types::Declareddeclared = dynamic_cast<Types::Declared&>(*type);
  186|                 // The variable could be a Variable or Enumerator
  187|                 AST::Variablevar;
  188|                 AST::Enumeratorenumor;
  189|                 if ((var = dynamic_cast<AST::Variable*>(declared.declaration())) != 0)
  190|                 {
  191|                     // It is a variable
  192|                     m_type = var->vtype();
  193|                     // Store a link to the variable itself (not its type)
  194|                     if (m_links)
  195|                         m_links->link(name_spectype);
  196|                     /*cout << "var type name is " << m_type_formatter->format(m_type) << endl;*/
  197|                 }
  198|                 else if ((enumor = dynamic_cast<AST::Enumerator*>(declared.declaration())) != 0)
  199|                 {
  200|                     // It is an enumerator
  201|                     m_type = 0; // we have no use for enums in type code
  202|                     // But still a link is needed
  203|                     if (m_links)
  204|                         m_links->link(name_spectype);
  205|                     /*cout << "enum type name is " << m_type_formatter->format(type) << endl;*/
  206|                 }
  207|                 else
  208|                 {
  209|                     throw nodeERROR(name_spec, "var was not a Variable nor Enumerator!");
  210|                 }
  211|             }
  212|             catch (const std::bad_cast &)
  213|             {
  214|                 if (dynamic_cast<Types::Unknown*>(type))
  215|                     throw nodeERROR(spec, "variable '" << name << "' was an Unknown type!");
  216|                 if (dynamic_cast<Types::Base*>(type))
  217|                     throw nodeERROR(spec, "variable '" << name << "' was a Base type!");
  218|                 throw nodeERROR(spec, "variable '" << name << "' wasn't a declared type!");
  219|             }
  220|         }
  221|         else
  222|         {
  223|             // Function lookup. m_type will be returnType. params are in m_params
  224|             AST::Scopescope = m_scope ;
  225|             if (!scope)
  226|                 scope = m_builder->scope();
  227|             // if (!scoped_name.empty()) func = m_lookup->lookupFunc(scoped_name, scope, m_params);
  228|             AST::Functionfunc = m_lookup->lookupFunc(namescopem_params);
  229|             if (!func)
  230|             {
  231|                 throw nodeERROR(name_spec, "Warning: function '" << name << "' not found!");
  232|             }
  233|             // Store a link to the function name
  234|             if (m_links)
  235|                 m_links->link(name_specfunc->declared(), LinkStore::FunctionCall);
  236|             // Now find returnType
  237|             m_type = func->return_type();
  238|         }
  239|     }
  240|     catch(const TranslateError& e)
  241|     {
  242|         m_scope = 0;
  243|         m_type = 0;
  244|         e.set_node(spec);
  245|         throw;
  246|     }
  247|     catch(const Types::wrong_type_cast &)
  248|     {
  249|         throw nodeERROR(spec, "wrong type error in TranslateVariable!");
  250|     }
  251|     catch(...)
  252|     {
  253|         throw nodeERROR(spec, "unknown error in TranslateVariable!");
  254|     }
  255|     m_scope = 0;
  256|     return 0;
  257| }
  258| 
  259| void
  260| SWalker::TranslateFunctionArgs(Ptree* args)
  261| {
  262|     // args: [ arg (, arg)* ]
  263|     while (args->Length())
  264|     {
  265|         Ptreearg = args->First();
  266|         // Translate this arg, TODO: m_params would be better as a vector<Type*>
  267|         m_type = 0;
  268|         Translate(arg);
  269|         m_params.push_back(m_type);
  270|         // Skip over arg and comma
  271|         args = Ptree::Rest(Ptree::Rest(args));
  272|     }
  273| }
  274| 
  275| Ptree*
  276| SWalker::TranslateFuncall(Ptree* node)  // and fstyle cas
  277| {
  278|     STrace trace("SWalker::TranslateFuncall");
  279|     // TODO: figure out how to deal with fstyle casts.. does it only apply to
  280|     // base types? eg: int(4.0) ?
  281|     // This is similar to TranslateVariable, except we have to check params..
  282|     // doh! That means more m_type nastiness
  283|     //
  284|     // [ postfix ( args ) ]
  285|     LOG(node);
  286|     // In translating the postfix the last var should be looked up as a
  287|     // function. This means we have to find the args first, and store them in
  288|     // m_params as a hint
  289|     Types::Type::vector save_params = m_params;
  290|     m_params.clear();
  291|     try
  292|     {
  293|         TranslateFunctionArgs(node->Third());
  294|     }
  295|     catch (...)
  296|     {
  297|         // Restore params before rethrowing exception
  298|         m_params = save_params;
  299|         throw;
  300|     }
  301| 
  302|     Postfix_Flag save_flag = m_postfix_flag;
  303|     try
  304|     {
  305|         m_postfix_flag = Postfix_Func;
  306|         Translate(node->First());
  307|     }
  308|     catch (...)
  309|     {
  310|         // Restore params and flag before rethrowing exception
  311|         m_params = save_params;
  312|         m_postfix_flag = save_flag;
  313|         throw;
  314|     }
  315| 
  316|     // Restore m_params since we're done with it now
  317|     m_params = save_params;
  318|     m_postfix_flag = save_flag;
  319|     return 0;
  320| }
  321| 
  322| Ptree*
  323| SWalker::TranslateExprStatement(Ptree* node)
  324| {
  325|     STrace trace("SWalker::TranslateExprStatement");
  326|     Translate(node->First());
  327|     return 0;
  328| }
  329| 
  330| Ptree*
  331| SWalker::TranslateUnary(Ptree* node)
  332| {
  333|     STrace trace("SWalker::TranslateUnary");
  334|     // [op expr]
  335|     if (m_links)
  336|         find_comments(node);
  337|     // TODO: lookup unary operator
  338|     Translate(node->Second());
  339|     return 0;
  340| }
  341| 
  342| Ptree*
  343| SWalker::TranslateAssign(Ptree* node)
  344| {
  345|     STrace trace("SWalker::TranslateAssign");
  346|     // [left = right]
  347|     // TODO: lookup = operator
  348|     m_type = 0;
  349|     Translate(node->First());
  350|     Types::Typeret_type = m_type;
  351|     Translate(node->Third());
  352|     m_type = ret_type;
  353|     return 0;
  354| }
  355| 
  356| //. Resolves the final type of any given Type. For example, it traverses
  357| //. typedefs and parameterized types, and resolves unknowns by looking them up.
  358| class TypeResolver : public Types::Visitor
  359| {
  360|     // TODO: Move to separate file???
  361| public:
  362|     //. Constructor - needs a Builder to resolve unknowns with
  363|     TypeResolver(Builder* b)
  364|     {
  365|         m_builder = b;
  366|     }
  367| 
  368|     //. Resolves the given type object
  369|     Types::Typeresolve(Types::Type* t)
  370|     {
  371|         m_type = t;
  372|         t->accept(this);
  373|         return m_type;
  374|     }
  375| 
  376|     //. Tries to resolve the given type object to a Scope
  377|     AST::Scopescope(Types::Type* t) throw (Types::wrong_type_cast, TranslateError)
  378|     {
  379|         return Types::declared_cast<AST::Scope>(resolve(t));
  380|     }
  381| 
  382|     //. Looks up the unknown type for a fresh definition
  383|     void visit_unknown(Types::Unknown* t)
  384|     {
  385|         m_type = m_builder->lookup()->resolveType(t);
  386|         if (!dynamic_cast<Types::Unknown*>(m_type))
  387|             m_type->accept(this);
  388|     }
  389| 
  390|     //. Recursively processes the aliased type
  391|     void visit_modifier(Types::Modifier* t)
  392|     {
  393|         t->alias()->accept(this);
  394|     }
  395| 
  396|     //. Checks for typedefs and recursively processes them
  397|     void visit_declared(Types::Declared* t)
  398|     {
  399|         AST::Typedeftdef = dynamic_cast<AST::Typedef*>(t->declaration());
  400|         if (tdef)
  401|         {
  402|             tdef->alias()->accept(this);
  403|         }
  404|         else
  405|             m_type = t;
  406|     }
  407| 
  408|     //. Processes the template type
  409|     void visit_parameterized(Types::Parameterized* t)
  410|     {
  411|         if (t->template_type())
  412|             t->template_type()->accept(this);
  413|     }
  414| 
  415| protected:
  416|     Builderm_builder//.< A reference to the builder object
  417|     Types::Typem_type//.< The type to return
  418| };
  419| 
  420| Ptree*
  421| SWalker::TranslateArrowMember(Ptree* node)
  422| {
  423|     STrace trace("SWalker::TranslateArrowMember");
  424|     // [ postfix -> name ]
  425|     m_type = 0;
  426|     m_scope = 0;
  427|     Postfix_Flag save_flag = m_postfix_flag;
  428|     m_postfix_flag = Postfix_Var;
  429|     Translate(node->First());
  430|     m_postfix_flag = save_flag;
  431|     // m_type should be a modifier to a declared to a class. Throw bad_cast if not
  432|     if (!m_type)
  433|     {
  434|         throw nodeERROR(node, "Unable to resolve type of LHS of ->");
  435|     }
  436|     try
  437|     {
  438|         m_scope = TypeResolver(m_builder).scope(m_type);
  439|     }
  440|     catch (const Types::wrong_type_cast&)
  441|     {
  442|         throw nodeERROR(node, "LHS of -> was not a scope!");
  443|     }
  444|     // Find member, m_type becomes the var type or func returnType
  445|     Translate(node->Third());
  446|     m_scope = 0;
  447|     return 0;
  448| }
  449| 
  450| Ptree*
  451| SWalker::TranslateDotMember(Ptree* node)
  452| {
  453|     STrace trace("SWalker::TranslateDotMember");
  454|     // [ postfix . name ]
  455|     m_type = 0;
  456|     m_scope = 0;
  457|     Postfix_Flag save_flag = m_postfix_flag;
  458|     m_postfix_flag = Postfix_Var;
  459|     Translate(node->First());
  460|     m_postfix_flag = save_flag;
  461|     LOG(parse_name(node->First()) << " resolved to " << m_type_formatter->format(m_type));
  462|     // m_type should be a declared to a class
  463|     if (!m_type)
  464|     {
  465|         throw nodeERROR(node, "Unable to resolve type of LHS of .");
  466|     }
  467|     LOG("resolving type to scope");
  468|     // Check for reference type
  469|     try
  470|     {
  471|         m_scope = TypeResolver(m_builder).scope(m_type);
  472|     }
  473|     catch (const Types::wrong_type_cast &)
  474|     {
  475|         throw nodeERROR(node, "Warning: LHS of . was not a scope: " << m_type_formatter->format(m_type));
  476|     }
  477|     // Find member, m_type becomes the var type or func returnType
  478|     LOG("translating third");
  479|     Translate(node->Third());
  480|     m_scope = 0;
  481|     return 0;
  482| }
  483| 
  484| Ptree*
  485| SWalker::TranslateIf(Ptree* node)
  486| {
  487|     STrace trace("SWalker::TranslateIf");
  488|     // [ if ( expr ) statement (else statement)? ]
  489|     if (m_links)
  490|         find_comments(node);
  491|     if (m_links)
  492|         m_links->span(node->First(), "file-keyword");
  493|     // Start a temporary namespace, in case expr is a declaration
  494|     m_builder->start_namespace("if"NamespaceUnique);
  495|     // Parse expression
  496|     Translate(node->Third());
  497|     // Store a copy of any declarations for use in the else block
  498|     std::vector<AST::Declaration*> decls = m_builder->scope()->declarations();
  499|     // Translate then-statement. If a block then we avoid starting a new ns
  500|     Ptreestmt = node->Nth(4);
  501|     if (stmt && stmt->First() && stmt->First()->Eq('{'))
  502|         TranslateBrace(stmt);
  503|     else
  504|         Translate(stmt);
  505|     // End the block and check for else
  506|     m_builder->end_namespace();
  507|     if (node->Length() == 7)
  508|     {
  509|         if (m_links)
  510|             m_links->span(node->Nth(5), "file-keyword");
  511|         AST::Namespacens = m_builder->start_namespace("else"NamespaceUnique);
  512|         ns->declarations().insert(
  513|             ns->declarations().begin(), decls.begin(), decls.end());
  514|         // Translate else statement, same deal as above
  515|         stmt = node->Nth(6);
  516|         if (stmt && stmt->First() && stmt->First()->Eq('{'))
  517|             TranslateBrace(stmt);
  518|         else
  519|             Translate(stmt);
  520|         m_builder->end_namespace();
  521|     }
  522|     return 0;
  523| }
  524| 
  525| Ptree*
  526| SWalker::TranslateSwitch(Ptree* node)
  527| {
  528|     STrace trace("SWalker::TranslateSwitch");
  529|     // [ switch ( expr ) statement ]
  530|     if (m_links)
  531|         find_comments(node);
  532|     if (m_links)
  533|         m_links->span(node->First(), "file-keyword");
  534|     m_builder->start_namespace("switch"NamespaceUnique);
  535|     // Parse expression
  536|     Translate(node->Third());
  537|     // Translate statement. If a block then we avoid starting a new ns
  538|     Ptreestmt = node->Nth(4);
  539|     if (stmt && stmt->First() && stmt->First()->Eq('{'))
  540|         TranslateBrace(stmt);
  541|     else
  542|         Translate(stmt);
  543|     // End the block and check for else
  544|     m_builder->end_namespace();
  545|     return 0;
  546| }
  547| 
  548| Ptree*
  549| SWalker::TranslateCase(Ptree* node)
  550| {
  551|     STrace trace("SWalker::TranslateCase");
  552|     // [ case expr : [expr] ]
  553|     if (m_links)
  554|         find_comments(node);
  555|     if (m_links)
  556|         m_links->span(node->First(), "file-keyword");
  557|     Translate(node->Second());
  558|     Translate(node->Nth(3));
  559|     return 0;
  560| }
  561| 
  562| Ptree*
  563| SWalker::TranslateDefault(Ptree* node)
  564| {
  565|     STrace trace("SWalker::TranslateDefault");
  566|     // [ default : [expr] ]
  567|     if (m_links)
  568|         find_comments(node);
  569|     if (m_links)
  570|         m_links->span(node->First(), "file-keyword");
  571|     Translate(node->Third());
  572|     return 0;
  573| }
  574| 
  575| Ptree*
  576| SWalker::TranslateBreak(Ptree* node)
  577| {
  578|     STrace trace("SWalker::TranslateBreak");
  579|     // [ break ; ]
  580|     if (m_links)
  581|         find_comments(node);
  582|     if (m_links)
  583|         m_links->span(node->First(), "file-keyword");
  584|     return 0;
  585| }
  586| 
  587| Ptree*
  588| SWalker::TranslateFor(Ptree* node)
  589| {
  590|     STrace trace("SWalker::TranslateFor");
  591|     // [ for ( stmt expr ; expr ) statement ]
  592|     if (m_links)
  593|         find_comments(node);
  594|     if (m_links)
  595|         m_links->span(node->First(), "file-keyword");
  596|     m_builder->start_namespace("for"NamespaceUnique);
  597|     // Parse expressions
  598|     Translate(node->Third());
  599|     Translate(node->Nth(3));
  600|     Translate(node->Nth(5));
  601|     // Translate statement. If a block then we avoid starting a new ns
  602|     Ptreestmt = node->Nth(7);
  603|     if (stmt && stmt->First() && stmt->First()->Eq('{'))
  604|         TranslateBrace(stmt);
  605|     else
  606|         Translate(stmt);
  607|     // End the block
  608|     m_builder->end_namespace();
  609|     return 0;
  610| }
  611| 
  612| Ptree*
  613| SWalker::TranslateWhile(Ptree* node)
  614| {
  615|     STrace trace("SWalker::TranslateWhile");
  616|     // [ while ( expr ) statement ]
  617|     if (m_links)
  618|         find_comments(node);
  619|     if (m_links)
  620|         m_links->span(node->First(), "file-keyword");
  621|     m_builder->start_namespace("while"NamespaceUnique);
  622|     // Parse expression
  623|     Translate(node->Third());
  624|     // Translate statement. If a block then we avoid starting a new ns
  625|     Ptreestmt = node->Nth(4);
  626|     if (stmt && stmt->First() && stmt->First()->Eq('{'))
  627|         TranslateBrace(stmt);
  628|     else
  629|         Translate(stmt);
  630|     // End the block and check for else
  631|     m_builder->end_namespace();
  632|     return 0;
  633| }
  634| 
  635| Ptree*
  636| SWalker::TranslatePostfix(Ptree* node)
  637| {
  638|     STrace trace("SWalker::TranslatePostfix");
  639|     // [ expr ++ ]
  640|     Translate(node->First());
  641|     return 0;
  642| }
  643| 
  644| Ptree*
  645| SWalker::TranslateParen(Ptree* node)
  646| {
  647|     STrace trace("SWalker::TranslateParen");
  648|     // [ ( expr ) ]
  649|     if (m_links)
  650|         find_comments(node);
  651|     Translate(node->Second());
  652|     return 0;
  653| }
  654| 
  655| Ptree*
  656| SWalker::TranslateCast(Ptree* node)
  657| {
  658|     STrace trace("SWalker::TranslateCast");
  659|     // ( type-expr ) expr   ..type-expr is type encoded
  660|     if (m_links)
  661|         find_comments(node);
  662|     Ptreetype_expr = node->Second();
  663|     //Translate(type_expr->First());
  664|     if (type_expr->Second()->GetEncodedType())
  665|     {
  666|         m_decoder->init(type_expr->Second()->GetEncodedType());
  667|         m_type = m_decoder->decodeType();
  668|         m_type = TypeResolver(m_builder).resolve(m_type);
  669|         if (m_type && m_links)
  670|             m_links->link(type_expr->First(), m_type);
  671|     }
  672|     else
  673|         m_type = 0;
  674|     Translate(node->Nth(3));
  675|     return 0;
  676| }
  677| 
  678| Ptree*
  679| SWalker::TranslateTry(Ptree* node)
  680| {
  681|     STrace trace("SWalker::TranslateTry");
  682|     // [ try [{}] [catch ( arg ) [{}] ]* ]
  683|     if (m_links)
  684|         find_comments(node);
  685|     if (m_links)
  686|         m_links->span(node->First(), "file-keyword");
  687|     m_builder->start_namespace("try"NamespaceUnique);
  688|     Translate(node->Second());
  689|     m_builder->end_namespace();
  690|     for (int n = 2n < node->Length(); n++)
  691|     {
  692|         // [ catch ( arg ) [{}] ]
  693|         Ptreecatch_node = node->Nth(n);
  694|         if (m_links)
  695|             m_links->span(catch_node->First(), "file-keyword");
  696|         m_builder->start_namespace("catch"NamespaceUnique);
  697|         Ptreearg = catch_node->Third();
  698|         if (arg->Length() == 2)
  699|         {
  700|             // Get the arg type
  701|             m_decoder->init(arg->Second()->GetEncodedType());
  702|             Types::Typearg_type = m_decoder->decodeType();
  703|             // Link the type
  704|             Types::Typearg_link = TypeResolver(m_builder).resolve(arg_type);
  705|             if (m_links)
  706|                 m_links->link(arg->First(), arg_link);
  707|             // Create a declaration for the argument
  708|             if (arg->Second() && arg->Second()->GetEncodedName())
  709|             {
  710|                 std::string name = m_decoder->decodeName(arg->Second()->GetEncodedName());
  711|                 m_builder->add_variable(m_linenonamearg_typefalse"exception");
  712|             }
  713|         }
  714|         // Translate contents of 'catch' block
  715|         Translate(catch_node->Nth(4));
  716|         m_builder->end_namespace();
  717|     }
  718|     return 0;
  719| }
  720| 
  721| Ptree*
  722| SWalker::TranslateArray(Ptree* node)
  723| {
  724|     STrace trace("SWalker::TranslateArray");
  725|     // <postfix> \[ <expr> \]
  726|     Translate(node->First());
  727|     Types::Typeobject = m_type;
  728| 
  729|     Translate(node->Third());
  730|     Types::Typearg = m_type;
  731| 
  732|     if (!object || !arg)
  733|     {
  734|         m_type = NULL;
  735|         return 0;
  736|     }
  737|     // Resolve final type
  738|     try
  739|     {
  740|         TypeFormatter tf;
  741|         LOG("ARRAY-OPER: " << tf.format(object) << " [] " << tf.format(arg));
  742|         AST::Functionfunc;
  743|         m_type = m_lookup->arrayOperator(objectargfunc);
  744|         if (func && m_links)
  745|         {
  746|             // Link the [ and ] to the function operator used
  747|             m_links->link(node->Nth(1), func->declared());
  748|             m_links->link(node->Nth(3), func->declared());
  749|         }
  750|     }
  751|     catch (const TranslateError& e)
  752|     {
  753|         e.set_node(node);
  754|         throw;
  755|     }
  756|     return 0;
  757| }
  758| 
  759| Ptree*
  760| SWalker::TranslateCond(Ptree* node)
  761| {
  762|     STrace trace("SWalker::TranslateCond");
  763|     Translate(node->Nth(0));
  764|     Translate(node->Nth(2));
  765|     Translate(node->Nth(4));
  766|     return 0;
  767| }
  768| 
  769| Ptree*
  770| SWalker::TranslateThis(Ptree* node)
  771| {
  772|     STrace trace("SWalker::TranslateThis");
  773|     if (m_links)
  774|         find_comments(node);
  775|     if (m_links)
  776|         m_links->span(node"file-keyword");
  777|     // Set m_type to type of 'this', stored in the name lookup for this func
  778|     m_type = m_lookup->lookupType("this");
  779|     return 0;
  780| }
  781| 
  782| 
  783| Ptree*
  784| SWalker::TranslateTemplateInstantiation(Ptree*)
  785| {
  786|     STrace trace("SWalker::TranslateTemplateInstantiation NYI");
  787|     return 0;
  788| }
  789| Ptree*
  790| SWalker::TranslateExternTemplate(Ptree*)
  791| {
  792|     STrace trace("SWalker::TranslateExternTemplate NYI");
  793|     return 0;
  794| }
  795| Ptree*
  796| SWalker::TranslateMetaclassDecl(Ptree*)
  797| {
  798|     STrace trace("SWalker::TranslateMetaclassDecl NYI");
  799|     return 0;
  800| }
  801| 
  802| Ptree*
  803| SWalker::TranslateStorageSpecifiers(Ptree*)
  804| {
  805|     STrace trace("SWalker::TranslateStorageSpecifiers NYI");
  806|     return 0;
  807| }
  808| Ptree*
  809| SWalker::TranslateFunctionBody(Ptree*)
  810| {
  811|     STrace trace("SWalker::TranslateFunctionBody NYI");
  812|     return 0;
  813| }
  814| 
  815| //Ptree* SWalker::TranslateEnumSpec(Ptree*) { STrace trace("SWalker::TranslateEnumSpec NYI"); return 0; }
  816| 
  817| Ptree*
  818| SWalker::TranslateAccessDecl(Ptree* node)
  819| {
  820|     STrace trace("SWalker::TranslateAccessDecl NYI");
  821|     if (m_links)
  822|         find_comments(node);
  823| #ifdef DEBUG
  824| 
  825|     node->Display2(std::cout);
  826| #endif
  827| 
  828|     return 0;
  829| }
  830| 
  831| Ptree*
  832| SWalker::TranslateUserAccessSpec(Ptree* node)
  833| {
  834|     STrace trace("SWalker::TranslateUserAccessSpec NYI");
  835|     if (m_links)
  836|         find_comments(node);
  837| #ifdef DEBUG
  838| 
  839|     node->Display2(std::cout);
  840| #endif
  841| 
  842|     return 0;
  843| }
  844| 
  845| 
  846| Ptree*
  847| SWalker::TranslateDo(Ptree* node)
  848| {
  849|     STrace trace("SWalker::TranslateDo NYI");
  850|     // [ do [{ ... }] while ( [...] ) ; ]
  851|     if (m_links)
  852|     {
  853|         find_comments(node);
  854|         m_links->span(node->First(), "file-keyword");
  855|         m_links->span(node->Third(), "file-keyword");
  856|     }
  857|     // Translate block
  858|     m_builder->start_namespace("do"NamespaceUnique);
  859|     // Translate statement. If a block then we avoid starting a new ns
  860|     Ptreestmt = node->Second();
  861|     if (stmt && stmt->First() && stmt->First()->Eq('{'))
  862|         TranslateBrace(stmt);
  863|     else
  864|         Translate(stmt);
  865|     // End the block and check for else
  866|     m_builder->end_namespace();
  867|     // Translate the while condition
  868|     Translate(node->Nth(4));
  869|     return 0;
  870| }
  871| 
  872| Ptree*
  873| SWalker::TranslateContinue(Ptree* node)
  874| {
  875|     STrace trace("SWalker::TranslateContinue NYI");
  876|     if (m_links)
  877|         find_comments(node);
  878|     if (m_links)
  879|         m_links->span(node->First(), "file-keyword");
  880|     return 0;
  881| }
  882| 
  883| Ptree*
  884| SWalker::TranslateGoto(Ptree* node)
  885| {
  886|     STrace trace("SWalker::TranslateGoto NYI");
  887|     if (m_links)
  888|         find_comments(node);
  889| #ifdef DEBUG
  890| 
  891|     node->Display2(std::cout);
  892| #endif
  893| 
  894|     return 0;
  895| }
  896| 
  897| Ptree*
  898| SWalker::TranslateLabel(Ptree* node)
  899| {
  900|     STrace trace("SWalker::TranslateLabel NYI");
  901|     if (m_links)
  902|         find_comments(node);
  903| #ifdef DEBUG
  904| 
  905|     node->Display2(std::cout);
  906| #endif
  907| 
  908|     return 0;
  909| }
  910| 
  911| 
  912| Ptree*
  913| SWalker::TranslateComma(Ptree* node)
  914| {
  915|     STrace trace("SWalker::TranslateComma");
  916|     // [ expr , expr (, expr)* ]
  917|     while (node)
  918|     {
  919|         Translate(node->First());
  920|         node = node->Rest();
  921|         if (node)
  922|             node = node->Rest();
  923|     }
  924|     return 0;
  925| }
  926| 
  927| Ptree*
  928| SWalker::TranslatePm(Ptree* node)
  929| {
  930|     STrace trace("SWalker::TranslatePm NYI");
  931| #ifdef DEBUG
  932| 
  933|     node->Display2(std::cout);
  934| #endif
  935| 
  936|     return 0;
  937| }
  938| 
  939| Ptree*
  940| SWalker::TranslateThrow(Ptree* node)
  941| {
  942|     STrace trace("SWalker::TranslateThrow");
  943|     // [ throw [expr] ]
  944|     if (m_links)
  945|         find_comments(node);
  946|     if (m_links)
  947|         m_links->span(node->First(), "file-keyword");
  948|     Translate(node->Second());
  949|     return 0;
  950| }
  951| 
  952| Ptree*
  953| SWalker::TranslateSizeof(Ptree* node)
  954| {
  955|     STrace trace("SWalker::TranslateSizeof");
  956|     // [ sizeof ( [type [???] ] ) ]
  957|     if (m_links)
  958|         find_comments(node);
  959|     if (m_links)
  960|         m_links->span(node->First(), "file-keyword");
  961|     // TODO: find the type for highlighting, and figure out what the ??? is
  962|     m_type = m_lookup->lookupType("int");
  963|     return 0;
  964| }
  965| 
  966| Ptree*
  967| SWalker::TranslateNew(Ptree* node)
  968| {
  969|     STrace trace("SWalker::TranslateNew NYI");
  970|     if (m_links)
  971|         find_comments(node);
  972| #ifdef DEBUG
  973| 
  974|     node->Display2(std::cout);
  975| #endif
  976| 
  977|     return 0;
  978| }
  979| 
  980| Ptree*
  981| SWalker::TranslateNew3(Ptree* node)
  982| {
  983|     STrace trace("SWalker::TranslateNew3 NYI");
  984|     if (m_links)
  985|         find_comments(node);
  986| #ifdef DEBUG
  987| 
  988|     node->Display2(std::cout);
  989| #endif
  990| 
  991|     return 0;
  992| }
  993| 
  994| Ptree*
  995| SWalker::TranslateDelete(Ptree* node)
  996| {
  997|     STrace trace("SWalker::TranslateDelete");
  998|     // [ delete [expr] ]
  999|     if (m_links)
 1000|         find_comments(node);
 1001|     if (m_links)
 1002|         m_links->span(node->First(), "file-keyword");
 1003|     Translate(node->Second());
 1004|     return 0;
 1005| }
 1006| 
 1007| Ptree*
 1008| SWalker::TranslateFstyleCast(Ptree* node)
 1009| {
 1010|     STrace trace("SWalker::TranslateFstyleCast NYI");
 1011|     if (m_links)
 1012|         find_comments(node);
 1013|     // [ [type] ( [expr] ) ]
 1014|     m_type = 0;
 1015|     //Translate(node->Third()); <-- unknown ptree???? FIXME
 1016|     m_decoder->init(node->GetEncodedType());
 1017|     m_type = m_decoder->decodeType();
 1018|     // TODO: Figure out if should have called a function for this
 1019|     return 0;
 1020| }
 1021| 
 1022| Ptree*
 1023| SWalker::TranslateUserStatement(Ptree* node)
 1024| {
 1025|     STrace trace("SWalker::TranslateUserStatement NYI");
 1026| #ifdef DEBUG
 1027| 
 1028|     node->Display2(std::cout);
 1029| #endif
 1030| 
 1031|     return 0;
 1032| }
 1033| 
 1034| Ptree*
 1035| SWalker::TranslateStaticUserStatement(Ptree* node)
 1036| {
 1037|     STrace trace("SWalker::TranslateStaticUserStatement NYI");
 1038| #ifdef DEBUG
 1039| 
 1040|     node->Display2(std::cout);
 1041| #endif
 1042| 
 1043|     return 0;
 1044| }
 1045| 
 1046| 
 1047| // vim: set ts=8 sts=4 sw=4 et: