コード例 #1
0
int jdip::context_parser::handle_scope(definition_scope *scope, token_t& token, unsigned inherited_flags)
{
  definition* decl;
  token = read_next_token(scope);
  for (;;)
  {
    switch (token.type)
    {
      case TT_TYPENAME:
      case TT_DECFLAG: case TT_DECLTYPE: case TT_DECLARATOR: case_TT_DECLARATOR:
      case TT_CLASS: case TT_STRUCT: case TT_ENUM: case TT_UNION: case TT_TILDE:
          decl = NULL;
          handle_declarator_block:
          if (handle_declarators(scope, token, inherited_flags, decl)) {
            FATAL_RETURN(1);
            while (token.type != TT_ENDOFCODE and token.type != TT_SEMICOLON and token.type != TT_LEFTBRACE and token.type != TT_RIGHTBRACE)
              token = read_next_token(scope);
          }
          handled_declarator_block:
          if (token.type != TT_SEMICOLON) {
            if (token.type == TT_LEFTBRACE || token.type == TT_ASM) {
              if (!(decl and decl->flags & DEF_OVERLOAD)) {
                token.report_error(herr, "Unexpected opening brace here; declaration is not a function");
                FATAL_RETURN(1);
                handle_function_implementation(lex,token,scope,herr);
              }
              else {
                definition_overload *ovr = ((definition_overload*)decl);
                if (ovr->implementation != NULL) {
                  token.report_error(herr, "Multiple implementations of function" FATAL_TERNARY("", "; old implementation discarded"));
                  delete_function_implementation(ovr->implementation);
                }
                ovr->implementation = handle_function_implementation(lex,token,scope,herr);
              }
              if (token.type != TT_RIGHTBRACE && token.type != TT_SEMICOLON) {
                token.report_error(herr, "Expected closing symbol to function");
                continue;
              }
            }
            else {
              token.report_errorf(herr, "Expected semicolon before %s following declaration");
              #if FATAL_ERRORS
                return 1;
              #else
                semicolon_bail:
                while (token.type != TT_SEMICOLON && token.type != TT_LEFTBRACE && token.type != TT_RIGHTBRACE && token.type != TT_ENDOFCODE)
                  token = read_next_token(scope);
                if (token.type == TT_LEFTBRACE) {
                  size_t depth = 1;
                  while (token.type != TT_ENDOFCODE) {
                    token = read_next_token(scope);
                    if (token.type == TT_LEFTBRACE) ++depth;
                    else if (token.type == TT_RIGHTBRACE) if (!--depth) break;
                  }
                }
              #endif
            }
          }
        break;
      
      case TT_EXTERN:
          token = read_next_token(scope);
          if (token.type == TT_STRINGLITERAL) {
            token = read_next_token(scope);
            if (token.type == TT_LEFTBRACE) {
              FATAL_RETURN_IF(handle_scope(scope, token, inherited_flags), 1);
              if (token.type != TT_RIGHTBRACE) {
                token.report_error(herr, "Expected closing brace to extern block");
                FATAL_RETURN(1);
              }
              break;
            }
          }
          else if (token.type == TT_TEMPLATE) {
            token = read_next_token(scope);
            if (token.type != TT_CLASS and token.type != TT_STRUCT and token.type != TT_DECLARATOR and token.type != TT_DECFLAG and token.type != TT_DEFINITION) {
              token.report_errorf(herr, "Expected template specialization following `extern template' directive; %s unhandled");
              FATAL_RETURN(1);
            }
            if (handle_template_extern(scope, token, inherited_flags))
              FATAL_RETURN(1);
            break;
          }
        goto handle_declarator_block;
      
      case TT_COMMA:
          token.report_error(herr, "Unexpected comma at this point.");
        return 1;
      
      case TT_SEMICOLON:
          /* Printing a warning here is advisable but unnecessary. */
        break;
      
      case TT_NAMESPACE: if (handle_namespace(scope,token)) return 1; break;
      case TT_LEFTPARENTH: {
          token.report_error(herr, "Stray opening parenthesis.");
          #if FATAL_ERRORS
            return 1;
          #else
            int bc = 1;
            while (bc) {
              token = read_next_token(scope);
              bc += token.type == TT_LEFTPARENTH;
              bc -= token.type == TT_RIGHTPARENTH;
            }
          #endif
        } break;
      case TT_RIGHTPARENTH: token.report_error(herr, "Stray closing parenthesis."); return 1;
      case TT_LEFTBRACKET:  token.report_error(herr, "Stray opening bracket."); return 1;
      case TT_RIGHTBRACKET: token.report_error(herr, "Stray closing bracket."); return 1;
      case TT_RIGHTBRACE:   return 0;
      case TT_LEFTBRACE: {
          token.report_error(herr, "Expected scope declaration before opening brace.");
          #if FATAL_ERRORS
            return 1;
          #else
            int bc = 1;
            while (bc) {
              token = read_next_token(scope);
              if (token.type == TT_ENDOFCODE) {
                token.report_error(herr, "Expected closing brace before end of code.");
                return 1;
              }
              bc += token.type == TT_LEFTBRACE;
              bc -= token.type == TT_RIGHTBRACE;
            }
          #endif
        } break;
      
      case TT_TYPEDEF:
        token = read_next_token(scope);
        if (handle_declarators(scope,token,inherited_flags | DEF_TYPENAME)) FATAL_RETURN(1); break;
      
      case TT_PUBLIC:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); }
        else token.report_error(herr, "Unexpected `public' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `public' token"); break;
      case TT_PRIVATE:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); inherited_flags |= DEF_PRIVATE; }
        else token.report_error(herr, "Unexpected `private' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `private' token"); break;
      case TT_PROTECTED:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); inherited_flags |= DEF_PROTECTED; }
        else token.report_error(herr, "Unexpected `protected' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `protected' token"); break;
      
      case TT_FRIEND:
          if (!(scope->flags & DEF_CLASS)) {
            token.report_error(herr, "`friend' statement may only appear in a class or structure");
            FATAL_RETURN(1);
            while ((token = read_next_token(scope)).type != TT_SEMICOLON && token.type != TT_RIGHTBRACE && token.type != TT_ENDOFCODE);
          }
          else {
            if (handle_friend(scope, token, (definition_class*)scope))
              FATAL_RETURN(1);
            if (token.type == TT_SEMICOLON)
              token = read_next_token(scope);
            else {
              token.report_errorf(herr, "Expected semicolon before %s");
              FATAL_RETURN(1);
            }
          }
        continue;
      
      case TT_USING:
          token = read_next_token(scope);
          if (token.type == TT_NAMESPACE) {
            token = lex->get_token_in_scope(scope, herr);
            if (token.type == TT_DEFINITION) {
              definition *d = read_qualified_definition(token, scope);
              if (!d) {
                token.report_errorf(herr, "Expected namespace-name following `namespace' token");
                FATAL_RETURN(1);
              }
              else {
                if (d->flags & DEF_NAMESPACE)
                  scope->use_namespace((definition_scope*)d);
                else
                  token.report_error(herr, "Expected namespace-name following `namespace' token");
              }
              if (token.type == TT_SEMICOLON)
                token = read_next_token(scope);
              else {
                token.report_errorf(herr, "Expected semicolon before %s");
                FATAL_RETURN(1);
              }
            }
            else {
              token.report_errorf(herr, "Expected namespace to use before %s");
              FATAL_RETURN(1);
            }
          }
          else {
            definition *usedef = read_qualified_definition(token, scope);
            if (usedef)
              scope->use_general(usedef->name, usedef);
            else {
              token.report_errorf(herr, "Using directive does not specify an object");
              FATAL_RETURN(1);
            }
            if (token.type != TT_SEMICOLON) {
              token.report_errorf(herr, "Expected semicolon before %s to terminate using directive");
              FATAL_RETURN(1);
            }
          }
        continue;
      
      case TT_SCOPE:
          token = read_next_token(ctex->get_global());
        continue;
      case TT_MEMBEROF:
          token.report_error(herr, "Unexpected (scope::*) reference");
        return 1;
      
      case TT_STATIC_ASSERT:
          token.report_error(herr, "Unimplemented: static assert");
        break;
      case TT_AUTO:
          token.report_error(herr, "Unimplemented: `auto' type inference");
        break;
      case TT_CONSTEXPR:
          token.report_error(herr, "Unimplemented: const expressions outside enum");
        break;
      
      case TT_DEFINITION: {
        if (token.def->flags & DEF_NAMESPACE) {
          definition_scope* dscope = (definition_scope*)token.def;
          token = read_next_token(scope);
          if (token.type == TT_SCOPE) {
            token = read_next_token(dscope);
            continue;
          }
          token.report_errorf(herr, "Expected `::' here to access namespace members");
          FATAL_RETURN(1); break;
        }
        if (token.def->flags & DEF_TEMPLATE)
          goto case_TT_DECLARATOR;
      }
      case TT_IDENTIFIER: {
          string tname(token.content.toString());
          if (tname == scope->name and (scope->flags & DEF_CLASS)) {
            token = read_next_token(scope);
            if (token.type != TT_LEFTPARENTH) {
              token.report_errorf(herr, "Expected constructor parmeters before %s");
              break;
            }
            
            full_type ft;
            ft.def = scope;
            token = read_next_token(scope);
            read_function_params(ft.refs, token, scope);
            if (handle_declarators(scope,token,ft,inherited_flags | DEF_TYPENAME,decl))
              FATAL_RETURN(1);
            goto handled_declarator_block;
          }
          token.report_error(herr, "Unexpected identifier in this scope (" + scope->name + "); `" + tname + "' does not name a type");
        } break;
      
      case TT_TEMPLATE:
        if (handle_template(scope, token, inherited_flags)) {
          FATAL_RETURN(1);
          goto semicolon_bail;
        }
        break;
      
      case TT_OPERATORKW: {
          full_type ft = read_operatorkw_cast_type(token, scope);
          if (!ft.def)
            return 1;
          if (!(decl = scope->overload_function("(cast)", ft, inherited_flags, token, herr)))
            return 1;
          goto handled_declarator_block;
      } break;
      
      case TT_ASM: case TT_SIZEOF: case TT_ISEMPTY: case TT_ALIGNOF: case TT_ALIGNAS:
      case TT_OPERATOR: case TT_ELLIPSIS: case TT_LESSTHAN: case TT_GREATERTHAN: case TT_COLON:
      case TT_DECLITERAL: case TT_HEXLITERAL: case TT_OCTLITERAL: case TT_STRINGLITERAL: case TT_CHARLITERAL:
      case TT_NEW: case TT_DELETE: case TTM_CONCAT: case TTM_TOSTRING: case TT_INVALID:
      case TT_CONST_CAST: case TT_STATIC_CAST: case TT_DYNAMIC_CAST: case TT_REINTERPRET_CAST:
      case TT_NOEXCEPT: case TT_TYPEID:
      #include <User/token_cases.h>
      default:
        token.report_errorf(herr, "Unexpected %s in this scope");
        break;
      
      case TT_ENDOFCODE:
        return 0;
    }
    token = read_next_token(scope);
  }
}
コード例 #2
0
ファイル: handle_scope.cpp プロジェクト: DarkAceZ/enigma-dev
int jdip::context_parser::handle_scope(definition_scope *scope, token_t& token, unsigned inherited_flags)
{
  definition* decl;
  token = read_next_token(scope);
  for (;;)
  {
    switch (token.type)
    {
      case TT_TYPENAME:
      case TT_DECFLAG: case TT_DECLTYPE: case TT_DECLARATOR: case_TT_DECLARATOR:
      case TT_CLASS: case TT_STRUCT: case TT_ENUM: case TT_UNION: case TT_TILDE:
          decl = NULL;
          handle_declarator_block:
          if (handle_declarators(scope, token, inherited_flags, decl)) {
            FATAL_RETURN(1);
            while (token.type != TT_ENDOFCODE and token.type != TT_SEMICOLON and token.type != TT_LEFTBRACE and token.type != TT_RIGHTBRACE)
              token = read_next_token(scope);
          }
          handled_declarator_block:
          if (token.type != TT_SEMICOLON) {
            if (token.type == TT_LEFTBRACE || token.type == TT_ASM) {
              if (!(decl and decl->flags & DEF_FUNCTION)) {
                token.report_error(herr, "Unexpected opening brace here; declaration is not a function");
                FATAL_RETURN(1);
                handle_function_implementation(lex,token,scope,herr);
              }
              else
                ((definition_function*)decl)->implementation = handle_function_implementation(lex,token,scope,herr);
              if (token.type != TT_RIGHTBRACE && token.type != TT_SEMICOLON) {
                token.report_error(herr, "Expected closing symbol to function");
                continue;
              }
            }
            else {
              token.report_errorf(herr, "Expected semicolon before %s following declaration");
              #if FATAL_ERRORS
                return 1;
              #else
                semicolon_bail:
                while (token.type != TT_SEMICOLON && token.type != TT_LEFTBRACE && token.type != TT_RIGHTBRACE && token.type != TT_ENDOFCODE)
                  token = read_next_token(scope);
                if (token.type == TT_LEFTBRACE) {
                  size_t depth = 1;
                  while (token.type != TT_ENDOFCODE) {
                    token = read_next_token(scope);
                    if (token.type == TT_LEFTBRACE) ++depth;
                    else if (token.type == TT_RIGHTBRACE) if (!--depth) break;
                  }
                }
              #endif
            }
          }
        break;
      
      case TT_EXTERN:
          token = read_next_token(scope);
          if (token.type == TT_STRINGLITERAL) {
            token = read_next_token(scope);
            if (token.type == TT_LEFTBRACE) {
              FATAL_RETURN_IF(handle_scope(scope, token, inherited_flags), 1);
              if (token.type != TT_RIGHTBRACE) {
                token.report_error(herr, "Expected closing brace to extern block");
                FATAL_RETURN(1);
              }
              break;
            }
          }
          else if (token.type == TT_TEMPLATE) {
            token = read_next_token(scope);
            if (token.type != TT_CLASS and token.type != TT_STRUCT and token.type != TT_DECLARATOR and token.type != TT_DEFINITION) {
              token.report_errorf(herr, "Expected template specialization following `extern template' directive; %s unhandled");
              FATAL_RETURN(1);
            }
          }
        goto handle_declarator_block;
      
      case TT_COMMA:
          token.report_error(herr, "Unexpected comma at this point.");
        return 1;
      
      case TT_SEMICOLON:
          /* Printing a warning here is advisable but unnecessary. */
        break;
      
      case TT_NAMESPACE: if (handle_namespace(scope,token)) return 1; break;
      case TT_LEFTPARENTH: {
          token.report_error(herr, "Stray opening parenthesis.");
          #if FATAL_ERRORS
            return 1;
          #else
            int bc = 1;
            while (bc) {
              token = read_next_token(scope);
              bc += token.type == TT_LEFTPARENTH;
              bc -= token.type == TT_RIGHTPARENTH;
            }
          #endif
        } break;
      case TT_RIGHTPARENTH: token.report_error(herr, "Stray closing parenthesis."); return 1;
      case TT_LEFTBRACKET:  token.report_error(herr, "Stray opening bracket."); return 1;
      case TT_RIGHTBRACKET: token.report_error(herr, "Stray closing bracket."); return 1;
      case TT_RIGHTBRACE:   return 0;
      case TT_LEFTBRACE: {
          token.report_error(herr, "Expected scope declaration before opening brace.");
          #if FATAL_ERRORS
            return 1;
          #else
            int bc = 1;
            while (bc) {
              token = read_next_token(scope);
              if (token.type == TT_ENDOFCODE) {
                token.report_error(herr, "Expected closing brace before end of code.");
                return 1;
              }
              bc += token.type == TT_LEFTBRACE;
              bc -= token.type == TT_RIGHTBRACE;
            }
          #endif
        } break;
      
      case TT_TYPEDEF:
        token = read_next_token(scope);
        if (handle_declarators(scope,token,inherited_flags | DEF_TYPENAME)) FATAL_RETURN(1); break;
      
      case TT_PUBLIC:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); }
        else token.report_error(herr, "Unexpected `public' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `public' token"); break;
      case TT_PRIVATE:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); inherited_flags |= DEF_PRIVATE; }
        else token.report_error(herr, "Unexpected `private' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `private' token"); break;
      case TT_PROTECTED:
        if (scope->flags & DEF_CLASS) { inherited_flags &= ~(DEF_PRIVATE | DEF_PROTECTED); inherited_flags |= DEF_PROTECTED; }
        else token.report_error(herr, "Unexpected `protected' token outside class scope.");
        if ((token = read_next_token(scope)).type != TT_COLON)
          token.report_error(herr, "Colon expected following `protected' token"); break;
      
      case TT_USING:
          token = read_next_token(scope);
          if (token.type == TT_NAMESPACE) {
            token = lex->get_token(herr);
            if (token.type == TT_IDENTIFIER) {
              definition* d = scope->look_up(token.content.toString());
              if (!d) {
                token.report_errorf(herr, "Expected id to use before %s");
                FATAL_RETURN(1);
              }
              else {
                if (d->flags & DEF_NAMESPACE)
                  scope->use_namespace((definition_scope*)d);
                else
                  token.report_error(herr, "Expected namespace name following `namespace' token");
              }
              token = read_next_token(scope);
            }
            else
              token.report_error(herr, "Expected namespace name following `namespace' token");
          }
          else {
            definition *usedef = read_qualified_definition(lex, scope, token, this, herr);
            if (usedef)
              scope->use_general(usedef->name, usedef);
            else {
              token.report_errorf(herr, "Using directive does not specify an object");
              FATAL_RETURN(1);
            }
            if (token.type != TT_SEMICOLON) {
              token.report_errorf(herr, "Expected semicolon before %s to terminate using directive");
              FATAL_RETURN(1);
            }
          }
        break;
      
      case TT_SCOPE:
          token = read_next_token(global);
        continue;
      case TT_DEFINITION: {
        if (token.def->flags & DEF_NAMESPACE) {
          definition_scope* dscope = (definition_scope*)token.def;
          token = read_next_token(scope);
          if (token.type == TT_SCOPE) {
            token = read_next_token(dscope);
            continue;
          }
          token.report_errorf(herr, "Expected `::' here to access namespace members");
          FATAL_RETURN(1); break;
        }
        if (token.def->flags & DEF_TEMPLATE)
          goto case_TT_DECLARATOR;
      }
      case TT_IDENTIFIER: {
          string tname(token.content.toString());
          if (tname == scope->name and (scope->flags & DEF_CLASS)) {
            token = read_next_token(scope);
            if (token.type != TT_LEFTPARENTH) {
              token.report_errorf(herr, "Expected constructor parmeters before %s");
              break;
            }
            
            full_type ft;
            ft.def = scope;
            token = read_next_token(scope);
            read_function_params(ft.refs, lex, token, scope, this, herr);
            if (handle_declarators(scope,token,ft,inherited_flags | DEF_TYPENAME,decl))
              FATAL_RETURN(1);
            goto handled_declarator_block;
          }
          token.report_error(herr, "Unexpected identifier in this scope; `" + tname + "' does not name a type");
        } break;
      
      case TT_TEMPLATE:
        if (handle_template(scope, token, inherited_flags)) {
          FATAL_RETURN(1);
          goto semicolon_bail;
        }
        break;
      
      case TT_OPERATORKW:
          token = read_next_token(scope);
          if (token.type != TT_DECLARATOR and token.type != TT_DECFLAG and token.type != TT_DECLTYPE) {
            token.report_errorf(herr, "Expected cast type to overload before %s");
            FATAL_RETURN(1);
          }
          else {
            lex_buffer lb(lex);
            while (token.type != TT_LEFTPARENTH and token.type != TT_LEFTBRACE and token.type != TT_SEMICOLON and token.type != TT_ENDOFCODE)
              lb.push(token), token = read_next_token(scope);
            if (token.type != TT_LEFTPARENTH) {
              token.report_error(herr, "Expected function parmeters before %s");
              FATAL_RETURN(1); break;
            }
            
            token.type = TT_ENDOFCODE; lb.push(token);
            token.type = TT_LEFTPARENTH;
            lb.reset(); token_t kick = lb.get_token(herr);
            full_type ft = read_fulltype(&lb, kick, scope, this, herr);
            
            string opname; {
              ref_stack my_func_refs;
              read_referencers_post(my_func_refs, lex, token, scope, this, herr);
              if (my_func_refs.empty() or my_func_refs.top().type != ref_stack::RT_FUNCTION) {
                token.report_error(herr, "Expected function parameters for operator overload");
                return 1;
              }
              opname = "operator " + ft.toString();
              ft.refs.append_c(my_func_refs);
            }
            
            definition_function *const df = new definition_function(opname, scope, ft.def, ft.refs, ft.flags, inherited_flags);
            decl = df;
            
            decpair ins = scope->declare(decl->name, decl);
            if (!ins.inserted) { arg_key k(df->referencers); decl = ((definition_function*)ins.def)->overload(k, df, herr); }
            goto handled_declarator_block;
          }
        break;
      
      case TT_ASM: case TT_SIZEOF: case TT_ISEMPTY:
      case TT_OPERATOR: case TT_ELLIPSIS: case TT_LESSTHAN: case TT_GREATERTHAN: case TT_COLON:
      case TT_DECLITERAL: case TT_HEXLITERAL: case TT_OCTLITERAL: case TT_STRINGLITERAL: case TT_CHARLITERAL:
      case TT_NEW: case TT_DELETE: case TTM_CONCAT: case TTM_TOSTRING: case TT_INVALID:
      #include <User/token_cases.h>
      default:
        token.report_errorf(herr, "Unexpected %s in this scope");
        break;
      
      case TT_ENDOFCODE:
        return 0;
    }
    token = read_next_token(scope);
  }
}
コード例 #3
0
int context_parser::handle_template(definition_scope *scope, token_t& token, unsigned inherited_flags)
{
  token = read_next_token(scope);
  if (token.type != TT_LESSTHAN) {
    token.report_error(herr, "Expected opening triangle bracket following `template' token");
    return ERROR_CODE;
  }
  token = read_next_token(scope);
  
  definition_template* temp = new definition_template("", scope, DEF_TEMPLATE | inherited_flags);
  
  for (;;) {
    string pname; // The name given to this parameter
    unsigned dtpflags = DEF_TEMPPARAM | DEF_DEPENDENT;
    
    definition_tempparam* dtn;
    if (token.type == TT_TYPENAME || token.type == TT_CLASS || token.type == TT_STRUCT) {
      token = lex->get_token(herr);
      if (token.type == TT_IDENTIFIER) {
        pname = token.content.toString();
        token = read_next_token(temp);
      }
      dtpflags |= DEF_TYPENAME;
    }
    else if (token.type == TT_DECFLAG || token.type == TT_DECLARATOR || token.type == TT_DECLTYPE) {
      full_type fts = read_fulltype(token, temp);
      pname = fts.refs.name;
    }
    else {
      if (token.type == TT_GREATERTHAN) break;
      token.report_errorf(herr, "Expected '>' token here before %s");
      FATAL_RETURN((delete temp, 1));
      break;
    }
    
    AST *ast = NULL;
    if (token.type == TT_OPERATOR) {
      if (token.content.len != 1 or *token.content.str != '=') {
        token.report_error(herr, "Unexpected operator here; value must be denoted by '='");
        FATAL_RETURN((void(delete temp),1));
      }
      token = read_next_token(temp);
      ast = new AST();
      ast->set_use_for_templates(true);
      astbuilder->parse_expression(ast, token, temp, precedence::comma+1);
    }
    dtn = new definition_tempparam(pname, temp, ast, dtpflags);
    
    temp->params.push_back(dtn);
    if (pname.empty()) {
      char nname[32];
      sprintf(nname, "<templateParam%03u>", (unsigned)temp->params.size());
    }
    else
      temp->use_general(pname, dtn);
    if (token.type == TT_GREATERTHAN)
      break;
    if (token.type != TT_COMMA)
      token.report_errorf(herr, "Expected '>' or ',' before %s");
    token = read_next_token(temp);
  }
  
  token = read_next_token(temp);
  
  // ========================================================================================================================================
  // =====: Handle template class definitions :==============================================================================================
  // ========================================================================================================================================
  
  if (token.type == TT_CLASS || token.type == TT_STRUCT)
  {
    unsigned protection = token.type == TT_CLASS? DEF_PRIVATE : 0;
    token = read_next_token(scope);
    definition_class *tclass;
    
    if (token.type == TT_IDENTIFIER) {
      regular_identifier:
      temp->name = token.content.toString();
      tclass = new definition_class(temp->name, temp, DEF_CLASS | DEF_TYPENAME);
      temp->def = tclass;
    
      scope->declare(temp->name, temp);
      
      token = read_next_token(scope);
      regular_template_class:
      
      if (token.type == TT_COLON) {
        if (handle_class_inheritance(tclass, token, tclass, protection))
          return 1;
      }
      
      if (token.type != TT_LEFTBRACE) {
        if (token.type == TT_SEMICOLON) {
          tclass->flags |= DEF_INCOMPLETE;
          return 0;
        }
        token.report_errorf(herr, "Opening brace for class body expected before %s");
        return 1;
      }
      
      if (handle_scope(tclass, token, protection))
        FATAL_RETURN(1);
      
      if (token.type != TT_RIGHTBRACE) {
        token.report_errorf(herr, "Expected closing brace to class body before %s");
        FATAL_RETURN(1);
      }
      
      return 0;
    }
    else if (token.type == TT_DEFINITION) {
      if (token.def->parent != scope)
        goto regular_identifier;
      
      if (not((token.def->flags & DEF_TEMPLATE) && (((definition_template*)token.def)->def->flags & DEF_CLASS))) {
        token.report_error(herr, "Expected class name for specialization; `" + token.def->name + "' does not name a template class");
        delete temp;
        return 1;
      }
      
      definition_template *basetemp = (definition_template*)token.def;
      
      token = read_next_token(temp);
      
      if (token.type != TT_LESSTHAN) {
        if (basetemp->def && (basetemp->def->flags & (DEF_CLASS | DEF_INCOMPLETE)) == (DEF_CLASS | DEF_INCOMPLETE)) {
          if (basetemp->params.size() != temp->params.size()) {
            token.report_error(herr, "Argument count differs from forward declaration");
            delete temp;
            return 1;
          }
          for (size_t i = 0; i < basetemp->params.size(); ++i) {
            if (basetemp->params[i]->flags != temp->params[i]->flags) {
              token.report_error(herr, "Parameter " + value((long)i).toString() + " of declaration differs from forward");
              delete temp;
              return 1;
            }
            if (!temp->params[i]->name.empty() && basetemp->params[i]->name != temp->params[i]->name) {
              definition_scope::defiter it = basetemp->using_general.find(basetemp->params[i]->name);
              if (it != basetemp->using_general.end())
                if (it->second == basetemp->params[i])
                  basetemp->using_general.erase(it);
                else token.report_warning(herr, "Template parameter `" + basetemp->params[i]->name
                                          + "' in forward declaration's using is not mapped to `" + temp->params[i]->name + "'");
              else if (!basetemp->params[i]->name.empty())
                token.report_warning(herr, "Template parameter `" + basetemp->params[i]->name
                                     + "' not found in forward declaration's using; cannot be renamed to `" + temp->params[i]->name + "'");
              
              basetemp->params[i]->name = temp->params[i]->name;
              basetemp->use_general(basetemp->params[i]->name, basetemp->params[i]);
            }
          }
          delete temp;
          temp = basetemp;
          tclass = (definition_class*)temp->def;
          goto regular_template_class;
        }
        token.report_errorf(herr, "Expected opening triangle bracket for template definition before %s");
        delete temp;
        return 1;
      }
      
      arg_key argk(basetemp->params.size());
      definition_template::specialization *spec = new definition_template::specialization(basetemp->params.size(), temp->params.size(), temp);
      argk.mirror_types(basetemp);
      size_t args_given = 0;
      for (;;++args_given)
      {
        token = read_next_token(temp);
        if (token.type == TT_GREATERTHAN)
          break;
        if (token.type == TT_SEMICOLON || token.type == TT_LEFTBRACE) {
          token.report_errorf(herr, "Expected closing triangle bracket to template parameters before %s");
          break;
        }
        
        if (token.type == TT_COMMA) continue;
        
        if (args_given >= basetemp->params.size()) {
          token.report_error(herr, "Too many parameters for template `" + basetemp->name + "'");
          delete temp; return 1;
        }
        
        if ((argk[args_given].type == arg_key::AKT_VALUE)
        and (token.type == TT_DEFINITION or token.type == TT_DECLARATOR) and (token.def->flags & DEF_TEMPPARAM))
        {
          for (size_t i = 0; i < temp->params.size(); ++i) if (temp->params[i] == token.def) {
            if (~temp->params[i]->flags & DEF_TYPENAME) {
              spec->key.arg_inds[i][++spec->key.arg_inds[i][0]] = args_given;
              argk[args_given].val() = VT_DEPENDENT;
              token = read_next_token(temp);
              goto handled_argk; // break 2;
            }
            else
              token.report_error(herr, "Type mismatch in passing parameter " + parse_bacics::visible::toString(args_given) + " to template specialization: real-valued parameter expected");
          }
        }
        
        if (read_template_parameter(argk, args_given, basetemp, token, temp)) {
          delete temp; // XXX: is this needed?
          return 1;
        }
        
        if (argk[args_given].type == arg_key::AKT_FULLTYPE) {
          definition *def = argk[args_given].ft().def;
          for (size_t i = 0; i < temp->params.size(); ++i) if (temp->params[i] == def) {
            spec->key.arg_inds[i][++spec->key.arg_inds[i][0]] = args_given;
            argk[args_given].ft().def = arg_key::abstract;
          }
        }
        
        handled_argk:
        
        if (token.type == TT_GREATERTHAN) {
          ++args_given;
          break;
        }
        if (token.type != TT_COMMA) {
          token.report_errorf(herr, "Comma or closing triangle bracket expected here before %s");
          break;
        }
      }
      if (check_read_template_parameters(argk, args_given, basetemp, token, herr)) {
        delete temp; // XXX: Needed?
        return 1;
      }
      
      // cout << "Specialization key: " << argk.toString() << endl;
      spec->filter = argk;
      definition_template::speclist &slist = basetemp->specializations;
      
      for (definition_template::speclist::iterator it = slist.begin(); it != slist.end(); ++it)
        if ((*it)->key.same_as(spec->key))
        {
          delete spec;
          spec = *it;
          
          if (~spec->spec_temp->flags & DEF_INCOMPLETE) {
            token.report_error(herr, "Cannot specialize template: specialization by this type already exists.");
            delete temp;
            return 1;
          }
          
          spec->spec_temp->using_general.clear(); // XXX: Maybe replace this with something to specifically delete template parameters, just in case? Could anything else be used? I'm thinking not.
          for (definition_template::piterator pit = temp->params.begin(); pit != temp->params.end(); ++pit)
            spec->spec_temp->use_general((*pit)->name, *pit);
          
          delete temp;
          temp = spec->spec_temp;
          break;
        }
      slist.push_back(spec);
      
      temp->name = basetemp->name + "<" + argk.toString() + ">";
      tclass = new definition_class(temp->name, temp, DEF_CLASS | DEF_TYPENAME);
      temp->def = tclass;
      tclass->instance_of = basetemp;
      
      token = read_next_token(scope);
      goto regular_template_class;
    }
    
    token.report_errorf(herr, "Expected class name here before %s");
    delete temp;
    return 1;
  }
  
  // ========================================================================================================================================
  // =====: Handle template function definitions :===========================================================================================
  // ========================================================================================================================================
  
  int funcflags = 0;
  if (token.type == TT_DECLARATOR || token.type == TT_DECFLAG || token.type == TT_DECLTYPE || token.type == TT_DEFINITION || token.type == TT_TYPENAME)
  {
    full_type funcrefs = read_fulltype(token, temp);
    if (!funcrefs.def) {
      if (token.type == TT_OPERATORKW) {
        funcflags = funcrefs.flags;
        if (!funcrefs.refs.empty()) {
          token.report_error(herr, "Program error: references attatched to typeless expression");
          return 1;
        }
        goto template_cast_operator;
      }
      token.report_error(herr, "Expected return type for template function at this point");
      delete temp;
      return 1;
    }
    
    if (funcrefs.refs.empty() || funcrefs.refs.top().type != ref_stack::RT_FUNCTION) {
      if (token.type == TT_DEFINITION && in_template(token.def)) {
        read_qualified_definition(token, scope); // We don't need to know the definition, just skip it. If we were a compiler, we'd need to know this. :P
        if (token.type == TT_OPERATOR && token.content.len == 1 && *token.content.str == '=') { // We don't need to know the value, either; we just need to skip it.
          token = read_next_token(scope);
          AST a; astbuilder->parse_expression(&a, token, scope, precedence::comma); // Read and discard; kind of a hack, but it's safe.
        }
        if (token.type != TT_SEMICOLON) {
          if (token.type == TT_LEFTPARENTH) // We're implementing a template function within a different class
          {
            read_referencers_post(funcrefs.refs, token, temp);
            if (token.type == TT_LEFTBRACE)
              delete_function_implementation(handle_function_implementation(lex, token, temp, herr));
            else
              token.report_error(herr, "I have no idea where I am.");
            delete temp;
            return 0;
          }
          token.report_errorf(herr, "Expected semicolon following template member definition before %s");
          FATAL_RETURN((void(delete temp), 1));
        }
        delete temp; // We're done with temp.
        return 0;
      }
      if (funcrefs.refs.ndef && funcrefs.refs.ndef->flags & DEF_HYPOTHETICAL) {
        // TODO: Do some error checking here to make sure whatever's being declared in that AST is a member of the template. Mark it non-extern.
      }
      else if (funcrefs.refs.ndef && (funcrefs.refs.ndef->flags & DEF_TYPED)) {
          definition_typed* dt = (definition_typed*)funcrefs.refs.ndef;
        if (dt->modifiers & builtin_flag__static)
          dt->flags &= ~DEF_INCOMPLETE; // TODO: Make structures OR static members by DEF_INCOMPLETE on creation; add error checking here
        else
          token.report_error(herr, "Definition of non-static member `" + dt->name + "'");
      }
      else
        token.report_errorf(herr, "Definition in template must be a function; `" + funcrefs.def->name + " " + funcrefs.refs.name + "' is not a function (at %s)");
      delete temp;
      return 1;
    }
    
    string funcname = funcrefs.refs.name;
    if (funcname.empty()) {
      if ((funcrefs.refs.ndef && funcrefs.refs.ndef->name == constructor_name) || is_potential_constructor(scope, funcrefs)) {
        funcname = constructor_name;
        if (token.type == TT_COLON) {
          // TODO: Actually store this. And the other one. :P
          handle_constructor_initializers(lex, token, scope, herr);
        }
      }
      else if (!funcrefs.refs.ndef) {
        token.report_error(herr, "Template functions must have names");
        delete temp;
        return 1;
      }
    }
    
    definition_function *func = NULL;
    definition *maybe = funcrefs.refs.ndef;
    if (!maybe)
      maybe = scope->find_local(funcname);
    if (maybe)
      if (!(maybe->flags & DEF_FUNCTION)) {
        token.report_error(herr, "Cannot redeclare " + maybe->kind() + " `" + funcname + "' as function in this scope");
        delete temp;
        return 1;
      }
      else func = (definition_function*)maybe;
    else {}
    
    definition_overload *tovr = new definition_overload(funcname, scope, funcrefs.def, funcrefs.refs, funcrefs.flags, DEF_FUNCTION);
    temp->def = tovr;
    
    if (!func)
      scope->declare(funcname, func = new definition_function(funcname, scope));
    func->overload(temp, herr);
    
    if (token.type == TT_COLON) {
      token.report_error(herr, "Unexpected colon; `" + funcname + "' is not a constructor");
      return 1;
    }
    
    if (token.type == TT_LEFTBRACE)
      tovr->implementation = (handle_function_implementation(lex, token, temp, herr));
    else if (token.type != TT_SEMICOLON) {
      token.report_errorf(herr, "Expected template function body or semicolon before %s");
      FATAL_RETURN(1);
    }
  }
  else if (token.type == TT_OPERATORKW) {
    template_cast_operator:
    full_type ft = read_operatorkw_cast_type(token, temp);
    definition_overload *ovr = new definition_overload("(cast)", scope, ft.def, ft.refs, ft.flags, DEF_FUNCTION | inherited_flags | funcflags);
    if (!ovr)
      return 1;
    if (token.type == TT_LEFTBRACE)
      ovr->implementation = handle_function_implementation(lex, token, scope, herr);
    else ovr->flags |= DEF_INCOMPLETE;
    temp->def = ovr;
    scope->overload_function("(cast)", temp, inherited_flags | funcflags, token, herr);
    return 0;
  }
  else if (token.type == TT_TEMPLATE) {
    // FIXME: OH MY F*****G WHAT
    // These templates are used when declaring functions which have templates as parameters,
    handle_template(temp, token, inherited_flags);
    delete temp;
    return 0;
  }
  else if (token.type == TT_FRIEND) {
    if (scope->flags & DEF_CLASS) {
      token = read_next_token(scope);
      if (token.type == TT_CLASS) {
        read_qualified_definition(token, temp);
        delete temp;
        if (token.type != TT_SEMICOLON)
          token.report_errorf(herr, "Expected semicolon to close friend statement before %s");
        return 0; // TODO: store this friend somewhere
      }
      else {
        read_fulltype(token, temp);
        delete temp;
        if (token.type != TT_SEMICOLON)
          token.report_errorf(herr, "Expected semicolon to close friend statement before %s");
        return 0; // TODO: store this friend somewhere
      }
      delete temp;
    }
    else {
      token.report_error(herr, "Unexpected `friend' statement: not in a class");
      delete temp;
      return 1;
    }
  }
  else {
    token.report_errorf(herr, "Expected class or function declaration following template clause before %s");
    delete temp;
    return ERROR_CODE;
  }
  
  
  return 0;
}