⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch19par.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
            iStatus = GetSyntaxItem ( SyntaxTable, RoutineNameTable, SyntaxLine,
                                      j, pNewBody );
            if (!iStatus)
            {
                i = 1;
                iStatus = TRUE;
            }
        }
    }   /* end of "while" getting items within this alternate */
    return iStatus;
}

/* ------------------------------------------------------------------ */

void FreeAlternates ( struct sSyntaxAlt** pFreeAlt )
{
    struct sSyntaxAlt* pNextAlt = NULL;
    struct sSyntaxBody* pFreeBody;
    /*
    *  Provided that we still have a pointer to an Alternate to
    *  free, get the address of the next one, free its contents,
    *  and free the alternate header itself:
    */
    while (*pFreeAlt!=NULL)
    {
        /* Get pointer to next: */
        pNextAlt  = (*pFreeAlt)->NextAlt;
        /* Get pointer to first body item, and free the body list: */
        pFreeBody = (*pFreeAlt)->ThisBody;
        FreeSyntaxItem ( &pFreeBody );
        /* Release the Alternate header: */
        free ( *pFreeAlt );
        /* And point to the next one (if any): */
        *pFreeAlt = pNextAlt;
    }

    /* Return the NULL signal to caller: */
    *pFreeAlt = pNextAlt;

    return;
}

/* ------------------------------------------------------------------ */

int GetSyntaxItem ( struct sSyntaxTableElement* SyntaxTable,
                    struct sRoutineNameTableElement* RoutineNameTable,
                    char* SyntaxLine,
                    int* j, struct sSyntaxBody* pNewBody )
{
    int iStatus = TRUE;
    int i;
    int k;
    int l;
    int m;
    int n;
    char Identifier[ROUTINE_NAME_LENGTH+1];
    int (*RoutineAddress) (void *);
    /*
    *  The Syntax Item that starts at subscript "j" starts with one
    *  of the following characters:
    *     a letter                  this is a reference to another
    *                               syntax name
    *     a left round parenthesis  this is a reference to a function
    *                               which will be called at recognition
    *                               time
    *     a left square bracket     this is a reference to a function
    *                               which will be called at code genera-
    *                               tion time
    *     a left curly bracket      this is a reference to a function
    *                               called during lexical analysis
    *     a double-quote            this is an explicit string which must
    *                               be present at this point in the text
    *                               which is being parsed
    *     anything else             an error in the syntax definition
    */
    switch (SyntaxLine[*j]) {
    case '(':
        /*
        *  This is the name of a routine to be called at parse time.
        *  We must change the value of BodyCheck. Get in the name
        *  of the routine to be called, and look its name up in the
        *  table of names and pointers, so that we can get a pointer
        *  to that routine:
        */
        (*j)++;
        iStatus = GetIdentifier ( SyntaxLine , Identifier , j );
        /* Skip the terminating right parenthesis: */
        (*j)++;
        iStatus = GetRoutinePointer ( RoutineNameTable, Identifier, &RoutineAddress );
        pNewBody->BodyCheck = RoutineAddress;
        break;
    case '[':
        /*
        *  This is the name of a routine to be called at code genera-
        *  tion time. This code is the same as that for BodyCheck above.
        */
        (*j)++;
        iStatus = GetIdentifier ( SyntaxLine , Identifier , j );
        /* Skip the terminating right square bracket: */
        (*j)++;
        iStatus = GetRoutinePointer ( RoutineNameTable, Identifier, &RoutineAddress );
        pNewBody->CodeGenerate = RoutineAddress;
        break;
    case '{':
        /*
        *  This is the name of a routine to be called during the
        *  lexical analysis phase.
        */
        (*j)++;
        iStatus = GetIdentifier ( SyntaxLine , Identifier , j );
        /* Skip the terminating right curly: */
        (*j)++;
        iStatus = GetRoutinePointer ( RoutineNameTable, Identifier, &RoutineAddress );
        pNewBody->LexCheck = RoutineAddress;
        break;
    case '\"':
        /*
        *  This is a character string for matching. We must change the
        *  value of BodyContents. Scan forward until we find the end of
        *  the string, which is an un-escaped double-quote. Also note
        *  the address of the start of the string.
        */
        k = *j + 1;  /* Substript of first character in string */
        m = 0;
        n = 0;
        for (i=k;(m==0);i++)
        {
            if (((SyntaxLine[i]=='\"') && (SyntaxLine[i+1]!='\\'))
            ||  (SyntaxLine[i]=='\n') || (SyntaxLine[i]=='\0'))
            {
                m = i;  /* Subscript of terminating quote */
                (*j) += n + 2;
            }
            n++;
        }
        /* Get enough memory for the length of this string: */
        l = m - k;
        pNewBody->BodyContents = malloc(l + 1);
        if(pNewBody->BodyContents == NULL)
        {
          printf("Out of memory on line %d - exiting.\n", __LINE__);
          exit(EXIT_FAILURE);
        }

        strcpy(pNewBody->BodyContents,"");
        strncat(pNewBody->BodyContents,SyntaxLine+k,(l));
        pNewBody->iSyntaxNumber = 0;
        pNewBody->BodyHead = NULL;
        break;
    default:
        if (isalpha(SyntaxLine[*j]))
        {
            /* This is a reference to a syntax item. Get the name and
            look it up: */
            k = GetSyntaxName ( SyntaxTable, SyntaxLine, j );
            pNewBody->iSyntaxNumber = k;
            pNewBody->BodyHead = SyntaxTable[k].pSyntaxPointer;
        }
        else
        {
            /*
            *  This is an error - the syntax definition is incorrect
            *  An error message could be issued here. At the very least,
            *  we signal this failure to the caller:
            */
            iStatus = FALSE;
        }
        break;
    };

    return iStatus;
}

/* ------------------------------------------------------------------ */

void FreeSyntaxItem ( struct sSyntaxBody** pFreeBody )
{
    struct sSyntaxBody* NextSyntaxBody = NULL;

    /*
    *  If the incoming pointer is not null, then release anything
    *  pointed at by this element, get the address of the next
    *  element, and free this element. Loop ruond till thw whole
    *  list is freed:
    */
    while (*pFreeBody!=NULL)
    {
        /* Get address of next element: */
        NextSyntaxBody = (*pFreeBody)->NextBody;
        /* If there is a character string to free, free it: */
        if (((*pFreeBody)->BodyContents)!=NULL)
        {
            free((*pFreeBody)->BodyContents);
        }
        /* free the list item itself: */
        free ( *pFreeBody );
        /* And point to the next one (if any): */
        *pFreeBody = NextSyntaxBody;
    }

    /* Return NULL pointer to caller: */
    *pFreeBody = NextSyntaxBody;

    return;
}

/* ------------------------------------------------------------------ */

void SkipSpaces ( char* SyntaxLine,
                  int* j )
{
    /*
    *  This moves parameter "j" forward past any whitespace, NOT
    *  including newline. So spaces and tabs are bypassed. On return
    *  "j" points to the first non-space character, which might be
    *  the end-of-string marker, '\0', or the first character of
    *  the next body item:
    */
    while (isspace(SyntaxLine[*j]) && (SyntaxLine[*j]!='\n'))
    {
        (*j) ++;
    }

    return;
}

/* ========================== Parse input buffer ======================= */

void RemoveSpaces ( char* InputBuffer )
{
   char *t;
   for (t=InputBuffer; *InputBuffer; !isspace(*InputBuffer) ?
                 *t++ = *InputBuffer++ : *InputBuffer++)
   {
      continue;
   }
   *t = '\0';
}


/* ------------------------------------------------------------------ */

/*
*  These are the parse routines for speeding up the parse process. They
*  are code implementations of some of the parse nodes, which will be
*  very much faster than the general technique. They are not necessary:
*  they merely make things faster.
*/

int parletter ( void* one )
{
    int iStatus;

    /*
    *  Check whether the character being pointed at by the first
    *  argument is a letter. If it is, then return TRUE,
    *  otherwise indicate failure.
    */
    if (isalpha(*(char*)one))
    {
        iStatus=TRUE;
    }
    else
        iStatus = FALSE;

    return iStatus;
}

int pardigit ( void* one )
{
    int iStatus;

    if (isdigit(*(char*)one))
    {
        iStatus=TRUE;
    }
    else
        iStatus = FALSE;

    return iStatus;
}

int paroctal ( void* one )
{
    int iStatus;

    if ((isdigit(*(char*)one)) && (*(char*)one!='8')
    &&  (*(char*)one!='9'))
    {
        iStatus=TRUE;
    }
    else
        iStatus = FALSE;

    return iStatus;
}

int parchar ( void* one )
{
    int iStatus;

    /*
    *  Allow everything except single quote, double quote, question-
    *  mark and back-slash:
    */

    if ((*(char*)one=='\'') || (*(char*)one=='\\')
    ||  (*(char*)one=='\?') || (*(char*)one=='\"'))
    {
        iStatus = FALSE;
    }
    else
        iStatus=TRUE;

    return iStatus;
}

/* ------------------------------------------------------------------ */

int BuildNewParseBody ( struct sParseNode*  pParentHead,
                        struct sParseNode*  pPreviousBody,
                        struct sParseNode** ppNewBody,
                        int    iFirstChar,
                        int    iLastChar )
{
    int iStatus;

    /*
    *  Get a new ParseBody item, chaining it to the previous item
    *  (if any). Then place in the ParseBody item the first and
    *  last addresses of the character string processed by it:
    */
printf("BuildNewParseBody TOP\n");
    iStatus = GetNewParseBody ( pParentHead, pPreviousBody, ppNewBody );
printf("BuildNewParseBody iStatus=%d\n",iStatus);

    if (iStatus==TRUE)
    {
        (*ppNewBody)->iFirstChar = iFirstChar;
        (*ppNewBody)->iLastChar  = iLastChar;
    }

    return iStatus;
}

/* ------------------------------------------------------------------ */

int GetNewParseBody ( struct sParseNode*  pParentHead,
                      struct sParseNode*  pPreviousBody,
                      struct sParseNode** ppNewBody )
{
    int iStatus = TRUE;
assert(pParentHead!=NULL);
    /*
    *  Get a new Parse Body item, and point the caller's
    *  given pointer to it:
    */
printf("GetNewParseBody TOP\n");
    *ppNewBody = malloc(sizeof (struct sParseNode));

    /*
    *  Chain this forward and back, and set the parent pointer:
    */
    if ((*ppNewBody)!=NULL)
    {
#ifdef PARDEBUG
        strcpy((*ppNewBody)->ParseNodeIdent,"PBD");
#endif
        pParentHead->ThisParse =     *ppNewBody;
        (*ppNewBody)->ParentParse   = pParentHead;
        (*ppNewBody)->NextParse     = NULL;
        (*ppNewBody)->PreviousParse = pPreviousBody;
        if (pPreviousBody!=NULL)
        {
            pPreviousBody->NextParse = *ppNewBody;
        }
        (*ppNewBody)->ThisParse  = NULL;
        (*ppNewBody)->ThisHead   = NULL;
        (*ppNewBody)->ThisBody   = NULL;
        (*ppNewBody)->CodeGenerate = NULL;
        (*ppNewBody)->iFirstChar = 0;
        (*ppNewBody)->iLastChar  = -1;
    }
    else
    {
        /*
        *  We were unable to allocate enough memory for another
        *  Parse Body item - this is bad! At his point we could
        *  issue an error message, collapse in a heap, or perform
        *  some undefined action that causes demons to fly from the
        *  user's nose - an error message is probably best.
        */
        printf("Out of memory on line %d - exiting.\n", __LINE__);
        exit(EXIT_FAILURE);
    }

    return iStatus;
}

/* ------------------------------------------------------------------ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -