📄 ch19par.c
字号:
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 + -