#include "array.h"
#include "clause.h"
#include "fol.h"
#include "memory.h"
#include "misc.h"
#include "symbol.h"
#include "term.h"
#include <stdint.h>
#ifdef DOC_BUILD_INTERNAL
#endif
#include "tptp_parser.h"
typedef enum tptparse_LexerTokenType {
  DOLLAR_WORD, DOLLAR_DOLLAR_WORD, LOWER_WORD, UPPER_WORD, SINGLE_QUOTED, DOUBLE_QUOTED, INT,
  GREATER_SIGN, LESS_SIGN, HASH, SLASH, SLOSH, R_L_BRACKET, R_R_BRACKET, COMMA, POINT, S_L_BRACKET, S_R_BRACKET, DOUBLE_POINT,
  EXCLAMATION, QUESTION, TILDE, VLINE, AND, LEFT_RIGHT_ARROW, L_IMPLICATION, R_IMPLICATION, LEFT_RIGHT_TILDE, TILDE_VLINE, TILDE_AND, STAR, PLUS, GENTZEN_ARROW,
  EQUAL, UNEQUAL, DOLLAR_TRUE, DOLLAR_FALSE,
  END_TOKEN
} tptparse_LexerTokenType;
typedef struct tptparse_LexerToken {
  tptparse_LexerTokenType type;
  char* content;
} tptparse_LexerToken;
TPTP_PARSESTATE tptparse_Init(FOLSTATE Folstate, SUBSTSTATE Sstate, SYMBOL Foltype, OHASH Namehash)
{
  TPTP_PARSESTATE parsstate;
  parsstate = memory_Malloc(fol_GetStateMemory(Folstate), sizeof(TPTP_PARSESTATE_NODE));
  parsstate->memory = fol_GetStateMemory(Folstate);
  parsstate->symbstate = fol_GetStateSymbolState(Folstate);
  parsstate->termstate = fol_GetStateTermstate(Folstate);
  parsstate->folstate = Folstate;
  parsstate->sstate = Sstate;
  parsstate->namehash = Namehash;
  parsstate->foltype = Foltype;
  parsstate->predicates = array_Create(parsstate->memory, 10);
  parsstate->folconstants = array_Create(parsstate->memory, 10);
  parsstate->folfunctions = array_Create(parsstate->memory, 10);
  parsstate->ariconstants = array_Create(parsstate->memory, 10);
  parsstate->distinctobjects = array_Create(parsstate->memory, 10);
  parsstate->id = 1;
  parsstate->inputlits = 0;
  parsstate->pos = 0;
  parsstate->has_equality = FALSE;
  parsstate->gclauses = NULL;
  parsstate->tpatterns = array_Create(parsstate->memory, 10);
  parsstate->cpatterns = array_Create(parsstate->memory, 10);
  return parsstate;
}
void tptparse_StateSetNamehash(TPTP_PARSESTATE Parsstate, OHASH Namehash)
{
  Parsstate->namehash = Namehash;
}
OHASH tptparse_StateGetNamehash(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->namehash;
}
ARRAY tptparse_StateGetPredicates(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->predicates;
}
void tptparse_StateSetPredicates(TPTP_PARSESTATE Parsstate, ARRAY Symbols)
{
  Parsstate->predicates = Symbols;
}
ARRAY tptparse_StateGetFolConstants(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->folconstants;
}
void tptparse_StateSetFolConstants(TPTP_PARSESTATE Parsstate, ARRAY Symbols)
{
  Parsstate->folconstants = Symbols;
}
unsigned tptparse_StateGetNumberInputLits(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->inputlits;
}
unsigned tptparse_StateGetId(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->id;
}
unsigned tptparse_StateGetNextIncrementId(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->id++;
}
MEMORY tptparse_StateGetMemory(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->memory;
}
FOLSTATE tptparse_StateGetFolstate(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->folstate;
}
SYMBSTATE tptparse_StateGetSymbstate(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->symbstate;
}
unsigned tptparse_StateGetNextId(TPTP_PARSESTATE Parsstate)
{
  return (Parsstate->id)++;
}
TERMSTATE tptparse_StateGetTermstate(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->termstate;
}
void tptparse_StateAddPredicate(TPTP_PARSESTATE Parsstate, SYMBOL Predicate)
{
  Parsstate->predicates = array_Add(Parsstate->memory, Parsstate->predicates, (intptr_t)Predicate);
}
void tptparse_StateAddFolConstant(TPTP_PARSESTATE Parsstate, SYMBOL Constant)
{
  Parsstate->folconstants = array_Add(Parsstate->memory, Parsstate->folconstants, (intptr_t)Constant);
}
void tptparse_StateAddFolFunction(TPTP_PARSESTATE Parsstate, SYMBOL Function)
{
  Parsstate->folfunctions = array_Add(Parsstate->memory, Parsstate->folfunctions, (intptr_t)Function);
}
void tptparse_StateSetFolFunctions(TPTP_PARSESTATE Parsstate, ARRAY Functions)
{
  Parsstate->folfunctions = Functions;
}
ARRAY tptparse_StateGetFolFunctions(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->folfunctions;
}
SUBSTSTATE tptparse_StateGetSubststate(TPTP_PARSESTATE Parsstate)
{
  return Parsstate->sstate;
}
void tptparse_freeToken(MEMORY mem, tptparse_LexerToken* token){
  if (token->content != NULL)
    memory_Free(mem, token->content, sizeof(char)*(strlen(token->content)+1));
  memory_Free(mem, token, sizeof(tptparse_LexerToken));
}
void tptparse_FreeTokenArray(TPTP_PARSESTATE Parsstate)
{
  unsigned i;
  for (i=0; i<array_GetSize(Parsstate->tokens); ++i) {
    tptparse_freeToken(tptparse_StateGetMemory(Parsstate),
         (tptparse_LexerToken*) array_GetElement(Parsstate->tokens, i));
  }
  array_Delete(tptparse_StateGetMemory(Parsstate), Parsstate->tokens);
  Parsstate->tokens = NULL;
}
void tptparse_Delete(TPTP_PARSESTATE Parsstate)
{
  MEMORY mem;
  mem = Parsstate->memory;
  if (Parsstate->predicates)
    array_Delete(mem, Parsstate->predicates);
  if (Parsstate->vartypes)
    array_Delete(mem, Parsstate->vartypes);
  if (Parsstate->folconstants)
    array_Delete(mem, Parsstate->folconstants);
  if (Parsstate->folfunctions)
    array_Delete(mem, Parsstate->folfunctions);
  if (Parsstate->ariconstants)
    array_Delete(mem, Parsstate->ariconstants);
  if (Parsstate->tpatterns)
    array_Delete(mem, Parsstate->tpatterns);
  if (Parsstate->cpatterns)
    array_Delete(mem, Parsstate->cpatterns);
  if (Parsstate->distinctobjects)
    array_Delete(mem, Parsstate->distinctobjects);
  memory_Free(mem, Parsstate, sizeof(TPTP_PARSESTATE_NODE));
}
void tptparse_FreeFofParsed(MEMORY mem, TPTP_FOF_PARSED tfp) {
  memory_Free(mem, tfp, sizeof(TPTP_FOF_PARSED_NODE));
}
void tptparse_DeleteFofParsed(MEMORY mem, TERMSTATE termstate, TPTP_FOF_PARSED tfp){
  array_Delete(mem, tfp->distinctobjects);
  tptparse_FreeFofParsed(mem, tfp);
}
BOOL is_alpha_numeric(char c){
  return (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c=='_'));
}
void failwith(const char* message, const char* function_name){
  misc_StartUserErrorReport();
  misc_UserErrorReport("\nIn %s:\n", function_name);
  misc_UserErrorReport("%s", message);
  misc_FinishUserErrorReport();
}
void assert(BOOL expression, const char* function_name){
  if (!expression)
    failwith("Assertion failed", function_name);
}
void assertWithMessage(BOOL expression, const char* format, char* message, const char* function_name){
  if (!expression){
    misc_StartUserErrorReport();
    misc_UserErrorReport("In %s:\n", function_name);
    misc_UserErrorReport(format, message);
    misc_UserErrorReport("\n");
    misc_FinishUserErrorReport();
  }
}
void tptparse_LexerTokenPrint(ARRAY lexer_tokens, unsigned i){
  tptparse_LexerToken* a = (tptparse_LexerToken *) array_GetElement(lexer_tokens, i);
  if (a->content != NULL)
    printf("%s ", a->content);
  switch (a->type){
    case DOLLAR_WORD: printf("DOLLAR_WORD");break;
    case DOLLAR_DOLLAR_WORD: printf("DOLLAR_DOLLAR_WORD");break;
    case LOWER_WORD: printf("LOWER_WORD");break;
    case UPPER_WORD: printf("UPPER_WORD");break;
    case SINGLE_QUOTED: printf("SINGLE_QUOTED");break;
    case DOUBLE_QUOTED: printf("DOUBLE_QUOTED");break;
    case INT: printf("INT");break;
    case GREATER_SIGN: printf("GREATER_SIGN");break;
    case LESS_SIGN: printf("LESS_SIGN");break;
    case HASH: printf("HASH");break;
    case SLASH: printf("SLASH");break;
    case SLOSH: printf("SLOSH");break;
    case R_L_BRACKET: printf("R_L_BRACKET");break;
    case R_R_BRACKET: printf("R_R_BRACKET");break;
    case COMMA: printf("COMMA");break;
    case POINT: printf("POINT");break;
    case S_L_BRACKET: printf("S_L_BRACKET");break;
    case S_R_BRACKET: printf("S_R_BRACKET");break;
    case DOUBLE_POINT: printf("DOUBLE_POINT");break;
    case EXCLAMATION: printf("EXCLAMATION");break;
    case QUESTION: printf("QUESTION");break;
    case TILDE: printf("TILDE");break;
    case VLINE: printf("VLINE");break;
    case AND: printf("AND");break;
    case LEFT_RIGHT_ARROW: printf("LEFT_RIGHT_ARROW");break;
    case L_IMPLICATION: printf("L_IMPLICATION");break;
    case R_IMPLICATION: printf("R_IMPLICATION");break;
    case LEFT_RIGHT_TILDE: printf("LEFT_RIGHT_TILDE");break;
    case TILDE_VLINE: printf("TILDE_VLINE");break;
    case TILDE_AND: printf("TILDE_AND");break;
    case STAR: printf("STAR");break;
    case PLUS: printf("PLUS");break;
    case EQUAL: printf("EQUAL");break;
    case UNEQUAL: printf("UNEQUAL");break;
    case DOLLAR_TRUE: printf("DOLLAR_TRUE");break;
    case DOLLAR_FALSE: printf("DOLLAR_FALSE");break;
    case END_TOKEN: printf("END_TOKEN");break;
    case GENTZEN_ARROW: printf("GENTZEN_ARROW");break;
  }
  printf(" \n");
}
void tptparse_LexerToString(ARRAY lexer_tokens) {
  for (unsigned i=0;i< (unsigned) (array_GetSize(lexer_tokens));i++){
    tptparse_LexerTokenPrint(lexer_tokens, i);
  }
  fflush(stdout);
}
ARRAY tptparse_add_TokenWithContent(MEMORY mem, ARRAY tokens, tptparse_LexerTokenType type, char* content, unsigned pos){
  tptparse_LexerToken* token;
  char *token_content;
  if (content != NULL){
    token_content = memory_Malloc(mem, (pos + 1) * sizeof(char));
    strncpy(token_content, content+0, pos);
    token_content[pos] = '\0';
  } else {
    token_content = NULL;
  }
  token = memory_Malloc(mem, sizeof(tptparse_LexerToken));
  token->type = type;
  token->content = token_content;
  return array_Add(mem, tokens, (intptr_t)token);
}
ARRAY tptparse_add_Token(MEMORY mem, ARRAY tokens, tptparse_LexerTokenType type) {
  return tptparse_add_TokenWithContent(mem, tokens, type, NULL, 0);
}
BOOL tptparse_check_Type(ARRAY tokens, unsigned pos, tptparse_LexerTokenType expected_type){
  return ((tptparse_LexerToken *) array_GetElement(tokens, pos))->type == expected_type;
}
ARRAY tptparse_Lex(FILE* Pfile, TPTP_PARSESTATE Parsstate) {
  ARRAY tokens;
  MEMORY mem;
  char *content;
  unsigned pos;
  mem = tptparse_StateGetMemory(Parsstate);
  tokens = array_Create(mem, 100);
  content = memory_Malloc(mem, 20000*sizeof(char));
  char c = fgetc(Pfile);
  while (c!= EOF) {
    switch (c) {
      case '%':
        while (c!='\n')
          c = fgetc(Pfile);
        c = fgetc(Pfile);
        break;
      case '/':
        c = fgetc(Pfile);
        if (c=='*'){
          c = fgetc(Pfile);
          int c1 = fgetc(Pfile);
          while (!(c=='*'&&c1=='/')){
            c = c1;
            c1 = fgetc(Pfile);
          }
          c = fgetc(Pfile);
        } else tokens = tptparse_add_Token(mem, tokens, SLASH);
        break;
      case '\'':
        content[0] = '\'';
        pos = 1;
        c = fgetc(Pfile);
        while (c!='\''){
          if (c=='\\'){
            c = fgetc(Pfile);
            content[pos] = c;
            pos++;
            c = fgetc(Pfile);
            continue;
          }
          content[pos] = c;
          pos++;
          c = fgetc(Pfile);
        }
        content[pos] = '\'';
        pos++;
        tokens = tptparse_add_TokenWithContent(mem, tokens, SINGLE_QUOTED, content, pos);
        c = fgetc(Pfile);
        break;
      case '"':
        content[0] = '"';
        pos = 1;
        c = fgetc(Pfile);
        while (c!='"'){
          if (c=='\\'){
            c = fgetc(Pfile);
            content[pos] = c;
            pos++;
            c = fgetc(Pfile);
            continue;
          }
          content[pos] = c;
          pos++;
          c = fgetc(Pfile);
        }
        content[pos] = '"';
        pos++;
        tokens = tptparse_add_TokenWithContent(mem, tokens, DOUBLE_QUOTED, content, pos);
        c = fgetc(Pfile);
        break;
      case '$':
        c = fgetc(Pfile);
        pos = 0;
        tptparse_LexerTokenType ttype;
        if (c=='$') {
          ttype = DOLLAR_DOLLAR_WORD;
        } else {
          ttype = DOLLAR_WORD;
        }
        while (is_alpha_numeric(c)){
            content[pos] = c;
            pos++;
            c = fgetc(Pfile);
        }
        content[pos] = '\0';
        if (ttype == DOLLAR_WORD && strcmp(content, "true") == 0)
          tokens = tptparse_add_Token(mem, tokens, DOLLAR_TRUE);
        else if (ttype == DOLLAR_WORD && strcmp(content, "false") == 0)
          tokens = tptparse_add_Token(mem, tokens, DOLLAR_FALSE);
        else
          tokens = tptparse_add_TokenWithContent(mem, tokens, ttype, content, pos);
        break;
      case '~':
        c = fgetc(Pfile);
        if (c == '|'){
          tokens = tptparse_add_Token(mem, tokens, TILDE_VLINE);
          c = fgetc(Pfile);
        } else if (c == '&'){
          tokens = tptparse_add_Token(mem, tokens, TILDE_AND);
          c = fgetc(Pfile);
        } else {
          tokens = tptparse_add_Token(mem, tokens, TILDE);
        }
        break;
      case '<':
        c = fgetc(Pfile);
        if (c == '=') {
          c = fgetc(Pfile);
          if (c == '>'){
            tokens = tptparse_add_Token(mem, tokens, LEFT_RIGHT_ARROW);
            c = fgetc(Pfile);
          } else {
            tokens = tptparse_add_Token(mem, tokens, L_IMPLICATION);
          }
        } else if (c == '~') {
          c = fgetc(Pfile);
          if (c == '>') {
            tokens = tptparse_add_Token(mem, tokens, LEFT_RIGHT_TILDE);
            c = fgetc(Pfile);
          } else {
            assertWithMessage(FALSE, "Unkown token in lexer: %s", &c, __func__);
            }
        } else {
          tokens = tptparse_add_Token(mem, tokens, LESS_SIGN);
          c = fgetc(Pfile);
        }
        break;
      case '=':
        c = fgetc(Pfile);
        if (c == '>') {
          tokens = tptparse_add_Token(mem, tokens, R_IMPLICATION);
          c = fgetc(Pfile);
        } else
          tokens = tptparse_add_Token(mem, tokens, EQUAL);
        break;
      case '!':
        c = fgetc(Pfile);
        if (c == '='){
          tokens = tptparse_add_Token(mem, tokens, UNEQUAL);
          c = fgetc(Pfile);
        } else
          tokens = tptparse_add_Token(mem, tokens, EXCLAMATION);
        break;
      case '|': tokens = tptparse_add_Token(mem, tokens, VLINE);c = fgetc(Pfile);break;
      case '*': tokens = tptparse_add_Token(mem, tokens, STAR);c = fgetc(Pfile);break;
      case '+': tokens = tptparse_add_Token(mem, tokens, PLUS);c = fgetc(Pfile);break;
      case '#': tokens = tptparse_add_Token(mem, tokens, HASH);c = fgetc(Pfile);break;
      case '?': tokens = tptparse_add_Token(mem, tokens, QUESTION);c = fgetc(Pfile);break;
      case '&': tokens = tptparse_add_Token(mem, tokens, AND);c = fgetc(Pfile);break;
      case '>': tokens = tptparse_add_Token(mem, tokens, GREATER_SIGN);c = fgetc(Pfile);break;
      case '\\': tokens = tptparse_add_Token(mem, tokens, SLOSH);c = fgetc(Pfile);break;
      case '(': tokens = tptparse_add_Token(mem, tokens, R_L_BRACKET);c = fgetc(Pfile);break;
      case ')': tokens = tptparse_add_Token(mem, tokens, R_R_BRACKET);c = fgetc(Pfile);break;
      case ',': tokens = tptparse_add_Token(mem, tokens, COMMA);c = fgetc(Pfile);break;
      case '.': tokens = tptparse_add_Token(mem, tokens, POINT);c = fgetc(Pfile);break;
      case '[': tokens = tptparse_add_Token(mem, tokens, S_L_BRACKET);c = fgetc(Pfile);break;
      case ']': tokens = tptparse_add_Token(mem, tokens, S_R_BRACKET);c = fgetc(Pfile);break;
      case ':': tokens = tptparse_add_Token(mem, tokens, DOUBLE_POINT);c = fgetc(Pfile);break;
      default:
        if (strchr("\n \t", c)!= NULL)
          c = fgetc(Pfile);
        else if ('a' <= c && c <= 'z') {
          pos = 0;
          do {
              content[pos] = c;
              pos++;
              c = fgetc(Pfile);
          }while (is_alpha_numeric(c));
          content[pos] = '\0';
            tokens = tptparse_add_TokenWithContent(mem, tokens, LOWER_WORD, content, pos);
        } else if ('A' <= c && c <= 'Z') {
          pos = 0;
          do {
              content[pos] = c;
              pos++;
              c = fgetc(Pfile);
          }while (is_alpha_numeric(c));
          tokens = tptparse_add_TokenWithContent(mem, tokens, UPPER_WORD, content, pos);
        } else if (c=='-'|| ('0' <= c && c <= '9')) {
          if (c == '-'){
            assertWithMessage(fgetc(Pfile)=='>', "Unkown token in lexer, expected > (gentzen arrow)", NULL, __func__);
            tokens = tptparse_add_Token(mem, tokens, GENTZEN_ARROW);
          } else{
     pos = 0;
            do {
                content[pos] = c;
                pos++;
                c = fgetc(Pfile);
            } while (('0' <= c && c <= '9'));
            tokens = tptparse_add_TokenWithContent(mem, tokens, INT, content, pos);
          }
        } else {
          assertWithMessage(FALSE, "Unkown token in lexer: %s", &c, __func__);
        }
        break;
    }
  }
  tokens = tptparse_add_Token(mem, tokens, END_TOKEN);
  memory_Free(mem, content, sizeof(char)*20000);
  return tokens;
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
#endif
char* tptparse_getIncludedFilePath(char *path, char *file, MEMORY mem) {
    file++;
    char *lastSlash = strrchr(path, '/');
    int pos = (lastSlash ? lastSlash-path+1 : 0);
    char *complete_path = memory_Malloc(mem, sizeof(char)*(pos+strlen(file)));
    strncpy(complete_path, path, pos);
    strncpy(&complete_path[pos], file, strlen(file)-1);
    complete_path[pos+strlen(file)-1] = '\0';
    FILE *Pfile = fopen(complete_path, "r");
    if (Pfile) {
      fclose(Pfile);
      return complete_path;
    }
    memory_Free(mem, complete_path, sizeof(char)*(pos+strlen(file)));
    char *tptp_env = getenv("TPTP");
    if (tptp_env) {
      complete_path = memory_Malloc(mem, sizeof(char)*(strlen(tptp_env)+strlen(file)+1));
      strncpy(complete_path, tptp_env, strlen(tptp_env));
      complete_path[strlen(tptp_env)] = '/';
      strncpy(&complete_path[strlen(tptp_env)+1], file, strlen(file)-1);
      complete_path[strlen(tptp_env)+strlen(file)] = '\0';
      Pfile = fopen(complete_path, "r");
      if (Pfile) {
        fclose(Pfile);
        return complete_path;
      }
      memory_Free(mem, complete_path, sizeof(char)*(strlen(tptp_env)+strlen(file)+1));
    }
    complete_path = memory_Malloc(mem, sizeof(char)*(pos+strlen(file)-1+7));
    strncpy(complete_path, path, pos);
    strncpy(&complete_path[pos], "../../", 7);
    memcpy(&(complete_path[pos+6]), file, strlen(file)-1);
    complete_path[pos+strlen(file)-1+6] = '\0';
    return complete_path;
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
TERM tptparse_ParseGeneralTerm(TPTP_PARSESTATE Parsstate, BOOL Atom, BOOL Is_infix)
{
  ARRAY tokens;
  ARRAY args;
  TERM term;
  MEMORY mem;
  intptr_t topsymbol, arg;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  FOLSTATE folstate;
  unsigned k;
  unsigned i;
  unsigned arity;
  mem = tptparse_StateGetMemory(Parsstate);
  folstate = tptparse_StateGetFolstate(Parsstate);
  symbstate = tptparse_StateGetSymbstate(Parsstate);
  termstate = tptparse_StateGetTermstate(Parsstate);
  tokens = Parsstate->tokens;
  i = Parsstate->pos;
  arity = 0;
  if (tptparse_check_Type(tokens, i, UPPER_WORD)){
    topsymbol = ohash_Search(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE) ((tptparse_LexerToken *) array_GetElement(tokens, i))->content);
    if (topsymbol != 0) {
      assertWithMessage(symbol_IsVariable(symbstate, topsymbol), "%s is not a variable. That should not happen\n", ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, __func__);
    }
    else {
      topsymbol = symbol_GetNextStandardVar(symbstate);
      tptparse_StateSetNamehash(Parsstate , ohash_Insert(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE)string_StringCopy(mem,((tptparse_LexerToken *) array_GetElement(tokens, i))->content), topsymbol, NULL, NULL));
      if (array_GetCapacity(Parsstate->vartypes) <= topsymbol) {
 Parsstate->vartypes = array_Extend(mem, Parsstate->vartypes, topsymbol);
 for (k=array_GetSize(Parsstate->vartypes);k<array_GetCapacity(Parsstate->vartypes);k++)
   array_NAddAtIndex(Parsstate->vartypes, k, fol_TypeTop(folstate));
      }
      else
 array_NAddAtIndex(Parsstate->vartypes, topsymbol, fol_TypeTop(folstate));
    }
    Parsstate->pos++;
    return term_Create(termstate, topsymbol, NULL);
  } else if (tptparse_check_Type(tokens, i, LOWER_WORD) || tptparse_check_Type(tokens, i, SINGLE_QUOTED)
  || tptparse_check_Type(tokens, i, DOLLAR_WORD) || tptparse_check_Type(tokens, i, DOLLAR_DOLLAR_WORD)) {
    if (tptparse_check_Type(tokens, i+1, R_L_BRACKET)) {
      args = array_Create(mem, 20);
      Parsstate->pos = i+1;
      do {
        Parsstate->pos++;
        arity++;
        args = array_Add(mem, args, (intptr_t) tptparse_ParseGeneralTerm(Parsstate, FALSE, Is_infix));
      } while (tptparse_check_Type(tokens, Parsstate->pos, COMMA));
      assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, R_R_BRACKET), "missing bracket after %s", ((tptparse_LexerToken *) array_GetElement(tokens, i))->content,__func__);
      Parsstate->pos++;
      assertWithMessage(arity>0, "function needs to have at least one argument: %s", ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, __func__);
      arg = ohash_Search(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE) ((tptparse_LexerToken *) array_GetElement(tokens, i))->content);
      if (arg != (OHASH_DATA_TYPE)NULL && symbol_GetArity(symbstate,arg) != -1) {
        assertWithMessage((unsigned)symbol_GetArity(symbstate,arg) == arity, "%s used with different number of arguments.",
            ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, __func__);
      }
      if (arg == (OHASH_DATA_TYPE)NULL) {
 if (Atom && !Is_infix) {
   arg = symbol_CreatePredicate(symbstate, fol_TypeBool(folstate), ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, arity);
   tptparse_StateAddPredicate(Parsstate, arg);
 }
 else {
   arg = symbol_CreateFunction(symbstate, fol_TypeTop(folstate), ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, arity);
   tptparse_StateAddFolFunction(Parsstate, arg);
 }
        tptparse_StateSetNamehash(Parsstate , ohash_Insert( tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE)string_StringCopy(mem,((tptparse_LexerToken *) array_GetElement(tokens, i))->content), arg, NULL, NULL));
      }
      term = term_CreateArity(termstate, arg, arity);
      for (unsigned j=0; j< arity; j++) {
        term_SetArgument(term, j, (TERM) array_GetElement(args, j));
        symbol_SetArgumentType(symbstate, arg, fol_TypeTop(folstate),j);
      }
      array_Delete(mem, args);
      return term;
    } else {
      arg = ohash_Search(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE) (((tptparse_LexerToken *) array_GetElement(tokens, i))->content));
      Parsstate->pos++;
      if (arg ==0 ) {
 if (Atom && !Is_infix) {
   arg = symbol_CreatePredicate(symbstate, fol_TypeBool(folstate), ((tptparse_LexerToken *) array_GetElement(tokens, i))->content, 0);
   tptparse_StateAddPredicate(Parsstate, arg);
 } else
   {
     arg = symbol_CreateConstant(symbstate, fol_TypeTop(folstate), ((tptparse_LexerToken *) array_GetElement(tokens, i))->content);
     tptparse_StateAddFolConstant(Parsstate, arg);
   }
 tptparse_StateSetNamehash(Parsstate , ohash_Insert(tptparse_StateGetNamehash(Parsstate),
             (OHASH_KEY_TYPE)string_StringCopy(mem,((tptparse_LexerToken *) array_GetElement(tokens, i))->content), arg, NULL, NULL));
      }
      return term_Create(termstate, arg, NULL);
    }
  } else if (tptparse_check_Type(tokens, i, DOLLAR_TRUE)) {
    Parsstate->pos++;
    return term_Create(termstate, fol_True(folstate), NULL);
  } else if (tptparse_check_Type(tokens, i, DOLLAR_FALSE)) {
    Parsstate->pos++;
    return term_Create(termstate, fol_False(folstate), NULL);
  } else if (tptparse_check_Type(tokens, i, DOUBLE_QUOTED)) {
    arg = ohash_Search(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE) (((tptparse_LexerToken *) array_GetElement(tokens, i))->content));
    Parsstate->pos++;
    if (arg==0) {
      arg = symbol_CreateConstant(symbstate, fol_TypeTop(folstate), ((tptparse_LexerToken *) array_GetElement(tokens, i))->content);
      Parsstate->distinctobjects = array_Add(Parsstate->memory, Parsstate->distinctobjects, arg);
      tptparse_StateSetNamehash(Parsstate , ohash_Insert( tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE)string_StringCopy(mem,((tptparse_LexerToken *) array_GetElement(tokens, i))->content), arg, NULL, NULL));
      tptparse_StateAddFolConstant(Parsstate, arg);
    }
    return term_Create(termstate, arg, NULL);
  } else {
      tptparse_LexerTokenPrint(Parsstate->tokens, Parsstate->pos);
      misc_StartUserErrorReport();
      misc_UserErrorReport("\nIn %s:\n", __func__);
      misc_UserErrorReport("incorrect term");
      misc_FinishUserErrorReport();
      return NULL;
  }
}
TERM tptparse_ParseFofAtomicFormula(TPTP_PARSESTATE Parsstate, BOOL* is_negated)
{
  ARRAY tokens;
  BOOL is_infix;
  TERM term;
  TERM atom;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  FOLSTATE folstate;
  SYMBOL topsymbol;
  int arity;
  int open_brackets;
  unsigned int i;
  folstate = tptparse_StateGetFolstate(Parsstate);
  symbstate = tptparse_StateGetSymbstate(Parsstate);
  termstate = tptparse_StateGetTermstate(Parsstate);
  tokens = Parsstate->tokens;
  is_infix = FALSE;
  open_brackets = 0;
  if(tptparse_check_Type(tokens, Parsstate->pos, R_L_BRACKET)) {
    open_brackets++;
  }
  for(i = Parsstate->pos + 1;; i++) {
    if(tptparse_check_Type(tokens, i, R_L_BRACKET)) {
      open_brackets++;
    }
    if (open_brackets == 0) {
      if (tptparse_check_Type(tokens, i, EQUAL) || tptparse_check_Type(tokens, i, UNEQUAL))
        is_infix = TRUE;
      break;
    }
    if(tptparse_check_Type(tokens, i, R_R_BRACKET)) {
      open_brackets--;
    }
  }
  term = tptparse_ParseGeneralTerm(Parsstate, TRUE, is_infix);
  #ifdef SPASS_CHECK
  assertWithMessage(Parsstate->pos == i, "Lookahead in tptparse_ParseFofAtomicFormula looked at the wrong symbol. This is an internal bug, please report.", NULL, __func__);
  #endif
  if(!is_infix) {
    return term;
  }
  #ifdef SPASS_CHECK
  assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, EQUAL) || tptparse_check_Type(tokens, Parsstate->pos, UNEQUAL), "Expected = or !=. This is an internal bug, please report.", NULL, __func__);
  #endif
  if(tptparse_check_Type(tokens, Parsstate->pos, UNEQUAL))
    *is_negated ^= TRUE;
  Parsstate->pos++;
  topsymbol = fol_Equal(folstate);
  if(!Parsstate->has_equality) {
    tptparse_StateAddPredicate(Parsstate, fol_Equal(folstate));
    Parsstate->has_equality = TRUE;
  }
  arity = symbol_GetArity(symbstate, topsymbol);
  atom = term_CreateArity(termstate, topsymbol, arity);
  term_SetArgument(atom, 0, term);
  term = tptparse_ParseGeneralTerm(Parsstate, FALSE, is_infix);
  term_SetArgument(atom, 1, term);
  return atom;
}
void tptparse_ParseCnfLiteral(TPTP_PARSESTATE Parsstate, ARRAY* Cons, ARRAY* Conc, ARRAY* Prem){
  MEMORY mem;
  ARRAY tokens;
  unsigned i;
  BOOL is_negated;
  TERM term;
  mem = tptparse_StateGetMemory(Parsstate);
  tokens = Parsstate->tokens;
  i = Parsstate->pos;
  is_negated = FALSE;
  if (tptparse_check_Type(tokens, i, TILDE)){
    is_negated = TRUE;
    Parsstate->pos++;
    if (tptparse_check_Type(tokens, i+1, R_L_BRACKET)) {
      Parsstate->pos++;
      term = tptparse_ParseFofAtomicFormula(Parsstate, &is_negated);
      assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, R_R_BRACKET), "Bracket mssing after negated literal.", NULL, __func__);
    } else {
      term = tptparse_ParseFofAtomicFormula(Parsstate, &is_negated);
    }
  } else {
    term = tptparse_ParseFofAtomicFormula(Parsstate, &is_negated);
  }
  if (is_negated)
    *Prem = array_Add(mem, *Prem, (intptr_t) term);
  else
    *Conc = array_Add(mem, *Conc, (intptr_t) term);
}
CLAUSE tptparse_ParseCnfDisjunction(TPTP_PARSESTATE Parsstate){
  MEMORY mem;
  ARRAY tokens;
  ARRAY Conc;
  ARRAY Cons;
  ARRAY Prem;
  CLAUSE clause;
  mem = tptparse_StateGetMemory(Parsstate);
  Conc = array_Create(mem, 100);
  Cons = array_Create(mem, 100);
  Prem = array_Create(mem, 100);
  tokens = Parsstate->tokens;
  tptparse_ParseCnfLiteral(Parsstate, &Cons, &Conc, &Prem);
  while (tptparse_check_Type(tokens, Parsstate->pos, VLINE)) {
    Parsstate->pos ++;
    tptparse_ParseCnfLiteral(Parsstate, &Cons, &Conc, &Prem);
  }
  clause = clause_CreateFromLiterals(mem, Cons, Conc, Prem, TRUE, tptparse_StateGetNextId(Parsstate));
  array_Delete(mem, Conc);
  array_Delete(mem, Cons);
  array_Delete(mem, Prem);
  return clause;
}
CLAUSE tptparse_ParseCnfFormula(TPTP_PARSESTATE Parsstate){
  ARRAY tokens;
  CLAUSE clause;
  unsigned i;
  tokens = Parsstate->tokens;
  i = Parsstate->pos;
  if (tptparse_check_Type(tokens, i, R_L_BRACKET)){
    Parsstate->pos = i+1;
    clause = tptparse_ParseCnfFormula(Parsstate);
    assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, R_R_BRACKET),
        "Missing closing bracket after CNF formula", NULL, __func__);
    Parsstate->pos++;
  } else {
    clause = tptparse_ParseCnfDisjunction(Parsstate);
  }
  return clause;
}
TERM tptparse_ParseFofQuantifiedFormula(TPTP_PARSESTATE Parsstate);
TERM tptparse_ParseFofLogicFormula(TPTP_PARSESTATE Parsstate);
TERM tptparse_ParseFofUnitFormula(TPTP_PARSESTATE Parsstate) {
  TERM term;
  if (tptparse_check_Type(Parsstate->tokens, Parsstate->pos, TILDE)){
    Parsstate->pos++;
    return fol_NegateToggle(Parsstate->folstate, tptparse_ParseFofUnitFormula(Parsstate));
  }
  else if (tptparse_check_Type(Parsstate->tokens, Parsstate->pos, QUESTION) || tptparse_check_Type(Parsstate->tokens, Parsstate->pos, EXCLAMATION)){
    return tptparse_ParseFofQuantifiedFormula(Parsstate);
  } else if (tptparse_check_Type(Parsstate->tokens, Parsstate->pos, R_L_BRACKET)) {
    return tptparse_ParseFofLogicFormula(Parsstate);
  } else {
    BOOL negate = FALSE;
    term = tptparse_ParseFofAtomicFormula(Parsstate, &negate);
    if (negate){
      return fol_NegateToggle(Parsstate->folstate, term);
    } else {
      return term;
    }
  }
}
TERM tptp_quantify(char* VarName, SYMBOL quantifier, TPTP_PARSESTATE Parsstate) {
  TERM atom;
  SYMBOL topsymbol;
  int k;
  topsymbol = ohash_Search(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE) ((tptparse_LexerToken *) array_GetElement(Parsstate->tokens, Parsstate->pos))->content);
  if (topsymbol != 0) {
    assertWithMessage(symbol_IsVariable(Parsstate->symbstate, topsymbol), "%s is not a variable. That should not happen\n", ((tptparse_LexerToken *) array_GetElement(Parsstate->tokens, Parsstate->pos))->content, __func__);
  }
  else {
    topsymbol = symbol_GetNextStandardVar(Parsstate->symbstate);
    tptparse_StateSetNamehash(Parsstate , ohash_Insert(tptparse_StateGetNamehash(Parsstate), (OHASH_KEY_TYPE)string_StringCopy(Parsstate->memory,((tptparse_LexerToken *) array_GetElement(Parsstate->tokens, Parsstate->pos))->content), topsymbol, NULL, NULL));
    if (array_GetCapacity(Parsstate->vartypes) <= topsymbol) {
      Parsstate->vartypes = array_Extend(Parsstate->memory, Parsstate->vartypes, topsymbol);
      for (k=array_GetSize(Parsstate->vartypes);k<array_GetCapacity(Parsstate->vartypes);k++)
        array_NAddAtIndex(Parsstate->vartypes, k, fol_TypeTop(Parsstate->folstate));
        }
    else
      array_NAddAtIndex(Parsstate->vartypes, topsymbol, fol_TypeTop(Parsstate->folstate));
  }
  atom = term_CreateArity(Parsstate->termstate, quantifier, 2);
  term_SetArgument(atom, 0, term_Create(Parsstate->termstate, topsymbol, NULL));
  return atom;
}
TERM tptparse_ParseFofQuantifiedFormula(TPTP_PARSESTATE Parsstate){
  SYMBOL topsymbol;
  TERM term;
  TERM new_term;
  TERM last_term;
  switch (((tptparse_LexerToken *) array_GetElement(Parsstate->tokens,Parsstate->pos))->type) {
    case EXCLAMATION:
      topsymbol = fol_Forall(Parsstate->folstate);
      break;
    case QUESTION:
      topsymbol = fol_Exist(Parsstate->folstate);
      break;
    default:
      topsymbol = fol_Exist(Parsstate->folstate);
      assertWithMessage(FALSE, "Unexpected quantification", NULL, __func__);
      break;
  }
  Parsstate->pos++;
  assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, S_L_BRACKET), "Expected list of variables", NULL, __func__);
  Parsstate->pos++;
  assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, UPPER_WORD), "Expected variable", NULL, __func__);
  term = tptp_quantify(((tptparse_LexerToken*) array_GetElement(Parsstate->tokens, Parsstate->pos))->content, topsymbol, Parsstate);
  last_term = term;
  Parsstate->pos++;
  while (!tptparse_check_Type(Parsstate->tokens, Parsstate->pos, S_R_BRACKET)){
    assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, COMMA), "Expected ','", NULL, __func__);
    Parsstate->pos++;
    assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, UPPER_WORD), "Expected variable", NULL, __func__);
    new_term = tptp_quantify(((tptparse_LexerToken*) array_GetElement(Parsstate->tokens, Parsstate->pos))->content, topsymbol, Parsstate);
    term_SetArgument(last_term, 1, new_term);
    last_term = new_term;
    Parsstate->pos++;
  }
  Parsstate->pos++;
  assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, DOUBLE_POINT), "Expected ':'", NULL, __func__);
  Parsstate->pos++;
  term_SetArgument(last_term, 1, tptparse_ParseFofUnitFormula(Parsstate));
  return term;
}
TERM tptparse_ParseFoFBinaryAssoc(TPTP_PARSESTATE Parsstate, TERM term, BOOL or){
  ARRAY arguments = array_Create(tptparse_StateGetMemory(Parsstate), 2);
  SYMBOL topsymbol;
  TERM atom;
  if (or){
    topsymbol = fol_Or(tptparse_StateGetFolstate(Parsstate));
  } else {
    topsymbol = fol_And(tptparse_StateGetFolstate(Parsstate));
  }
  arguments = array_Add(tptparse_StateGetMemory(Parsstate), arguments, (intptr_t) term);
  while ((tptparse_check_Type(Parsstate->tokens, Parsstate->pos, VLINE) && or)
       ||(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, AND) && !or)) {
    Parsstate->pos++;
    arguments = array_Add(tptparse_StateGetMemory(Parsstate), arguments, (intptr_t) tptparse_ParseFofUnitFormula(Parsstate));
  }
  atom = term_CreateArity(tptparse_StateGetTermstate(Parsstate), topsymbol, array_GetSize(arguments));
  for (int i=0;i<array_GetSize(arguments);i++){
    term_SetArgument(atom, i, (TERM) array_GetElement(arguments, i));
  }
  array_Delete(tptparse_StateGetMemory(Parsstate), arguments);
  return atom;
}
TERM tptparse_ParseFofLogicFormula(TPTP_PARSESTATE Parsstate){
  TERM term;
  TERMSTATE termstate;
  SYMBOL topsymbol = (SYMBOL) NULL;
  TERM atom;
  unsigned arity;
  int offset = 0;
  BOOL flag = TRUE;
  BOOL in_brackets = FALSE;
  BOOL negate = FALSE;
  termstate = tptparse_StateGetTermstate(Parsstate);
  if (tptparse_check_Type(Parsstate->tokens, Parsstate->pos, R_L_BRACKET)){
    Parsstate->pos++;
    in_brackets = TRUE;
  }
  term = tptparse_ParseFofUnitFormula(Parsstate);
  switch (((tptparse_LexerToken *) array_GetElement(Parsstate->tokens,Parsstate->pos))->type) {
    case LEFT_RIGHT_ARROW:
      topsymbol = fol_Equiv(Parsstate->folstate);
      break;
    case L_IMPLICATION:
      topsymbol = fol_Implies(Parsstate->folstate);
      offset = 1;
      break;
    case R_IMPLICATION:
      topsymbol = fol_Implies(Parsstate->folstate);
      break;
    case AND:
      flag = FALSE;
      term = tptparse_ParseFoFBinaryAssoc(Parsstate, term, FALSE);
      break;
    case VLINE:
      flag = FALSE;
      term = tptparse_ParseFoFBinaryAssoc(Parsstate, term, TRUE);
      break;
    case LEFT_RIGHT_TILDE:
      topsymbol = fol_Equiv(Parsstate->folstate);
      negate = TRUE;
      break;
    case TILDE_AND:
    case TILDE_VLINE:
      assertWithMessage(FALSE, "Unkown or unimplemented operator", NULL, __func__);
      break;
    default:
      flag = FALSE;
      break;
  }
  if (flag){
    Parsstate->pos++;
    arity = 2;
    atom = term_CreateArity(termstate, topsymbol, arity);
    term_SetArgument(atom, offset, term);
    term = tptparse_ParseFofUnitFormula(Parsstate);
    term_SetArgument(atom, (offset+1)%2, term);
    term = atom;
  }
  if (negate){
    term = fol_NegateToggle(tptparse_StateGetFolstate(Parsstate), term);
  }
  if (in_brackets) {
    assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, R_R_BRACKET), "Expected closing bracket", NULL, __func__);
    Parsstate->pos++;
  }
  return term;
}
TERM tptparse_ParseFofFormula(TPTP_PARSESTATE Parsstate){
  if (tptparse_check_Type(Parsstate->tokens, Parsstate->pos, S_L_BRACKET)) {
    assertWithMessage(FALSE, "Sequent Caclulus not_implemented", NULL, __func__);
  }
  return tptparse_ParseFofLogicFormula(Parsstate);
}
TPTP_FORMULA tptparse_CnfAnnotated(TPTP_PARSESTATE Parsstate)
{
  MEMORY mem;
  CLAUSE clause;
  ARRAY tokens;
  unsigned i;
  tptparse_LexerToken *token;
  TPTP_FORMULA formula;
  mem = tptparse_StateGetMemory(Parsstate);
  formula = tptp_AllocateFormula(mem);
  tokens = Parsstate->tokens;
  i = Parsstate->pos;
  token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage((tptparse_check_Type(tokens, i, LOWER_WORD)
       && strcmp(token->content, TPTP_LangCNF)==0),
      "Expected cnf language", NULL, __func__);
  tptp_SetLanguage(formula, TPTP_LangCNF);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, R_L_BRACKET),
      "Expected opening bracket for CNF", NULL, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, INT)
      || tptparse_check_Type(tokens, i, LOWER_WORD)
      || tptparse_check_Type(tokens, i, SINGLE_QUOTED),
      "Formula name has to be int, lower word or 'quoted'", NULL, __func__);
  tptp_SetName(formula, token->content);
  token->content = NULL;
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, COMMA),
      "Expected comma after formula name", NULL, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, LOWER_WORD),
      "expected formula role", NULL, __func__);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleAxiom);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleHypothesis);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleDefinition);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleLemma);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleTheorem);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleCorollary);
  tptp_TrySettingRole(formula, token->content, TPTP_RolePlain);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleConjecture);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleNegatedConjecture);
  assertWithMessage((tptp_GetRole(formula) != NULL), "no supported formula role: %s",
      token->content, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, COMMA),
      "Expected comma after formula role", NULL, __func__);
  Parsstate->pos = i+1;
  clause = tptparse_ParseCnfFormula(Parsstate);
  if ((strcmp(tptp_GetRole(formula), TPTP_RoleConjecture) == 0)
      || (strcmp(tptp_GetRole(formula), TPTP_RoleNegatedConjecture) == 0)
      || (strcmp(tptp_GetRole(formula), TPTP_RoleHypothesis) == 0)) {
    clause_MarkConjecture(clause, TRUE);
  }
  tptp_SetClause(formula, clause);
  assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, R_R_BRACKET),
      "Expected closing bracket after FOF formula", NULL, __func__);
  assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos+1, POINT),
      "Point expected at the end of fof formula", NULL, __func__);
  Parsstate->pos+=2;
  return formula;
}
TPTP_FORMULA tptparse_FofAnnotated(TPTP_PARSESTATE Parsstate)
{
  MEMORY mem;
  TERM term;
  ARRAY tokens;
  unsigned i;
  tptparse_LexerToken *token;
  TPTP_FORMULA formula;
  mem = tptparse_StateGetMemory(Parsstate);
  formula = tptp_AllocateFormula(mem);
  tokens = Parsstate->tokens;
  i = Parsstate->pos;
  token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage((tptparse_check_Type(tokens, i, LOWER_WORD)
       && strcmp(token->content, TPTP_LangFOF)==0),
      "Expected fof language", NULL, __func__);
  tptp_SetLanguage(formula, TPTP_LangFOF);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, R_L_BRACKET),
      "Expected opening bracket for FOF", NULL, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, INT)
      || tptparse_check_Type(tokens, i, LOWER_WORD)
      || tptparse_check_Type(tokens, i, SINGLE_QUOTED),
      "Formula name has to be int, lower word or 'quoted'", NULL, __func__);
  tptp_SetName(formula, token->content);
  token->content = NULL;
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, COMMA),
      "Expected comma after formula name", NULL, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, LOWER_WORD),
      "expected formula role", NULL, __func__);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleAxiom);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleHypothesis);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleDefinition);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleLemma);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleTheorem);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleCorollary);
  tptp_TrySettingRole(formula, token->content, TPTP_RolePlain);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleConjecture);
  tptp_TrySettingRole(formula, token->content, TPTP_RoleNegatedConjecture);
  assertWithMessage((tptp_GetRole(formula) != NULL), "no supported formula role: %s",
      token->content, __func__);
  ++i; token = ((tptparse_LexerToken *) array_GetElement(tokens, i));
  assertWithMessage(tptparse_check_Type(tokens, i, COMMA),
      "Expected comma after formula role", NULL, __func__);
  Parsstate->pos = i+1;
  term = tptparse_ParseFofFormula(Parsstate);
  tptp_SetTerm(formula, term);
  assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos, R_R_BRACKET),
      "Expected closing bracket after FOF formula", NULL, __func__);
  assertWithMessage(tptparse_check_Type(tokens, Parsstate->pos+1, POINT),
      "Point expected at the end of fof formula", NULL, __func__);
  Parsstate->pos+=2;
  return formula;
}
ARRAY tptp_RecurseOnFile(TPTP_PARSESTATE Parsstate, FILE* FilePtr, char* FilePath, ARRAY Formulae)
{
  MEMORY mem;
  ARRAY tokens;
  tptparse_LexerToken *token;
  unsigned pos;
  char *includePath;
  TPTP_FORMULA formula;
  mem = tptparse_StateGetMemory(Parsstate);
  Parsstate->pos = 0;
  Parsstate->tokens = tptparse_Lex(FilePtr, Parsstate);
  tokens = NULL;
  while (!tptparse_check_Type(Parsstate->tokens, Parsstate->pos, END_TOKEN)) {
    token = (tptparse_LexerToken *)array_GetElement(Parsstate->tokens, Parsstate->pos);
    assertWithMessage(tptparse_check_Type(Parsstate->tokens, Parsstate->pos, LOWER_WORD),
        "TPTP top level block doesn't start with LOWER_WORD: %s",
        token->content,
        __func__);
    if (strcmp(token->content, "include") == 0) {
      tokens = Parsstate->tokens;
      pos = Parsstate->pos;
      Parsstate->tokens = NULL;
      assertWithMessage(tptparse_check_Type(tokens, ++pos, R_L_BRACKET),
   "Expected opening bracket after include", NULL, __func__);
      assertWithMessage(tptparse_check_Type(tokens, ++pos, SINGLE_QUOTED),
   "Expected filename (in quotes)", NULL, __func__);
      includePath = ((tptparse_LexerToken*)array_GetElement(tokens, pos))->content;
      assertWithMessage(tptparse_check_Type(tokens, ++pos, R_R_BRACKET),
   "Expected closing bracket (did this file use unsupported include annotations?)",
   NULL, __func__);
      assertWithMessage(tptparse_check_Type(tokens, ++pos, POINT),
   "Expected point after include", NULL, __func__);
      char* path = tptparse_getIncludedFilePath(FilePath, includePath, mem);
      FILE* Pfile = fopen(path, "r");
      assertWithMessage((NULL!=Pfile), "Include %s not found.\n", includePath, __func__);
      Formulae = tptp_RecurseOnFile(Parsstate, Pfile, path, Formulae);
      memory_Free(mem, path, sizeof(char)*(strlen(path)+1));
      Parsstate->tokens = tokens;
      Parsstate->pos = pos+1;
    }
    else if (strcmp(token->content, TPTP_LangCNF) == 0) {
      formula = tptparse_CnfAnnotated(Parsstate);
      tptp_SetFilename(formula, string_StringCopy(mem, string_GetPostfix(FilePath, '/')));
      Formulae = array_Add(mem, Formulae, (intptr_t)formula);
    } else if (strcmp(token->content, TPTP_LangFOF) == 0) {
      formula = tptparse_FofAnnotated(Parsstate);
      tptp_SetFilename(formula, string_StringCopy(mem, string_GetPostfix(FilePath, '/')));
      Formulae = array_Add(mem, Formulae, (intptr_t)formula);
    }
    else {
      misc_StartUserErrorReport();
      misc_UserErrorReport("In %s: TPTP top level block language %s not implemented.\n",
      __func__, token->content);
      misc_FinishUserErrorReport();
    }
  }
  tptparse_FreeTokenArray(Parsstate);
  return Formulae;
}
ARRAY tptparse_ParseFile(TPTP_PARSESTATE Parsstate, FILE* FilePtr, char* FilePath)
{
  FOLSTATE folstate;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  MEMORY mem;
  ARRAY formulae;
  SYMBOL do1, do2;
  TPTP_FORMULA formula;
  TERM neq;
  unsigned i, j;
  char* name;
  symbstate = tptparse_StateGetSymbstate(Parsstate);
  folstate = tptparse_StateGetFolstate(Parsstate);
  termstate = tptparse_StateGetTermstate(Parsstate);
  mem = tptparse_StateGetMemory(Parsstate);
  Parsstate->vartypes = array_Create(mem, symbol_GetMaxVars(symbstate));
  array_Claim(Parsstate->vartypes);
  for (i=0; i<array_GetSize(Parsstate->vartypes); ++i)
    array_SetElement(Parsstate->vartypes, i, fol_TypeTop(folstate));
  symbol_ResetStandardVarCounterNonZero(symbstate);
  formulae = tptp_RecurseOnFile(Parsstate, FilePtr, FilePath, array_Create(mem, 100));
  for (i=0; i<array_GetSize(formulae); ++i) {
    formula = (TPTP_FORMULA)array_GetElement(formulae, i);
    if (strcmp(TPTP_LangCNF, tptp_GetLanguage(formula)) == 0) {
      if (1) clause_NormalizeVarsEstablishTypes(tptparse_StateGetSubststate(Parsstate),
      tptparse_StateGetTermstate(Parsstate),
      Parsstate->foltype,
      tptp_GetClause(formula),
      Parsstate->vartypes,
      (TYPE)((intptr_t)NULL));
    }
  }
  for (i=0; i<array_GetSize(Parsstate->distinctobjects); ++i) {
    do1 = (SYMBOL)array_GetElement(Parsstate->distinctobjects, i);
    for (j=i+1; j<array_GetSize(Parsstate->distinctobjects); ++j) {
      do2 = (SYMBOL)array_GetElement(Parsstate->distinctobjects, j);
#ifdef SPASSCHECK
      if (symbol_Equal(do1, do2)) {
        misc_StartUserErrorReport();
        misc_UserErrorReport("In %s:\n", __func__);
        misc_UserErrorReport("Error: distinct object symbols %s and %s are equal\n",
                             symbol_GetName(do1), symbol_GetName(do2));
        misc_FinishUserErrorReport();
      }
#endif
      formula = tptp_AllocateFormula(mem);
      tptp_SetLanguage(formula, TPTP_LangFOF);
      tptp_SetRole(formula, TPTP_RoleAxiom);
      name = (char*)memory_Malloc(mem, sizeof(char)*(strlen(symbol_GetName(symbstate, do1))+strlen(symbol_GetName(symbstate, do2))+11));
      sprintf(name, "distinct_%s_%s", symbol_GetName(symbstate, do1), symbol_GetName(symbstate, do2));
      tptp_SetName(formula, name);
      neq = term_CreateArity(termstate, fol_Equal(folstate), 2);
      term_SetArgument(neq, 0, term_Create(termstate, do1, NULL));
      term_SetArgument(neq, 1, term_Create(termstate, do2, NULL));
      neq = fol_NegateToggle(folstate, neq);
      tptp_SetTerm(formula, neq);
      array_Add(mem, formulae, (intptr_t)formula);
    }
  }
#if 0
  if(array_GetSize(conjectures) > 1) {
    misc_StartUserErrorReport();
    misc_UserErrorReport("\nIn %s:\n", __func__);
    misc_UserErrorReport("Expected at most one (negated) conjecture in the file, but found %u many conjectures", array_GetSize(conjectures));
    misc_FinishUserErrorReport();
  }
#endif
  return formulae;
}
