📄 语法分析ll1b.txt
字号:
/********************************************************************/
/* 函数名 gettoken */
/* 功 能 从Token序列中取出一个Token */
/* 说 明 从文件中存的Token序列中依次取一个单词,作为当前单词. */
/********************************************************************/
void CparseLL1::gettoken(TokenType *p)
{
FILE *fp2;
/*按只读方式打开文件*/
fp2=fopen("Tokenlist","rb");
if (fp2==NULL)
{ AfxGetApp()->m_pMainWnd->MessageBox("不能打开token文件");
return;
}
fseek(fp2,fpnum*sizeof(TokenType),0);
fread(p,sizeof(TokenType),1,fp2);
fpnum++;
fclose(fp2);
}
/********************************************************************/
/* 函数名 syntaxError */
/* 功 能 语法错误处理函数 */
/* 说 明 将函数参数message指定的错误信息格式化写入列表文件listing */
/* 设置错误追踪标志Error为TRUE */
/********************************************************************/
void CparseLL1::syntaxError(char * message)
{ fprintf(listing,"\n >> ");
/* 将出错行号lineno和语法错误信息message格式化写入文件listing */
fprintf(listing,"Syntax error at line %d: %s",lineno,message);
/* 设置错误追踪标志Error为TRUE,防止错误进一步传递 */
Error = TRUE;
}
void CparseLL1::process1()
{
Push(2, DOT);
Push(1, ProgramBody);
Push(1, DeclarePart);
Push(1, ProgramHead);
}
/********************************************************************/
/* 函数名 CparseLL1::process2() */
/* 功 能 处理程序头,并生成程序头节点Phead. */
/* 说 明 产生式为:PROGRAM ProgramName */
/********************************************************************/
void CparseLL1::process2()
{
Push(1,ProgramName);
Push(2,PROGRAM);
TreeNode **t=PopPA();
currentP=newPheadNode();
(*t)=currentP;
/*程序头节点没有兄弟节点,下面的声明用用根节点的child[1]指向*/
}
void CparseLL1::process3()
{
Push(2,ID);
strcpy( currentP->name[0] ,currentToken.Sem);
currentP->idnum++;
}
void CparseLL1::process4()
{
Push(1,ProcDec);
Push(1,VarDec);
Push(1,TypeDec);
}
void CparseLL1::process5()
{
}
void CparseLL1::process6()
{
Push(1,TypeDeclaration);
}
void CparseLL1::process7()
{
Push(1,TypeDecList);
Push(2,TYPE);
TreeNode **t=PopPA();
currentP = newTypeNode(); /*生成Type作为标志的结点,它的子结点都是
类型声明*/
(*t) = currentP; /*头结点的兄弟结点指针指向此结点*/
PushPA(&((*currentP).sibling)); /* 压入指向变量声明节点的指针*/
PushPA(&((*currentP).child[0])); /*压入指向第一个类型声明节点的指针*/
}
void CparseLL1::process8()
{
Push(1,TypeDecMore);
Push(2,SEMI);
Push(1,TypeName);
Push(2,EQ);
Push(1,TypeId);
TreeNode **t=PopPA();
currentP = newDecNode(); /*生成一个表示类型声明的结点,
不添任何信息*/
(*t) = currentP; /*若是第一个,则是Type类型的子结点指向当前结点,
否则,是上一个类型声明的兄弟结点*/
PushPA(&((*currentP).sibling));
}
void CparseLL1::process9()
{
PopPA();
}
void CparseLL1::process10()
{
Push(1,TypeDecList);
}
void CparseLL1::process11()
{
Push(2,ID);
strcpy( (*currentP).name[0] ,currentToken.Sem);
currentP->idnum++;
}
void CparseLL1::process12()
{
Push(1,BaseType);
/*由于数组基类型的问题,这里不能直接用currentP->kind.dec=IntegerK;
而应该这么做,以适应所有情形*/
temp=&(currentP->kind.dec);
}
void CparseLL1::process13()
{
Push(1,StructureType);
}
void CparseLL1::process14()
{
Push(2,ID);
/*声明的类型部分为类型标识符*/
(*currentP).kind.dec=IdK;
strcpy(currentP->attr.type_name ,currentToken.Sem);
}
void CparseLL1::process15()
{
Push(2,INTEGER);
/*声明的类型部分为整数类型*/
(*temp)=IntegerK;
}
void CparseLL1::process16()
{
Push(2,CHAR1);
/*声明的类型部分为子符类型*/
(*temp) =CharK;
}
void CparseLL1::process17()
{
Push(1,ArrayType);
}
void CparseLL1::process18()
{
Push(1,RecType);
}
void CparseLL1::process19()
{
Push(1,BaseType);
Push(2,OF);
Push(2,RMIDPAREN);
Push(1,Top);
Push(2,UNDERANGE);
Push(1,Low);
Push(2,LMIDPAREN);
Push(2,ARRAY);
/*声明的类型为数组类型*/
(*currentP).kind.dec=ArrayK;
temp = &(currentP->attr.ArrayAttr.childtype);
}
void CparseLL1::process20()
{
Push(2,INTC);
/*存储数组的下届*/
(*currentP).attr.ArrayAttr.low=atoi(currentToken.Sem);
}
void CparseLL1::process21()
{
Push(2,INTC);
/*存储数组的上届*/
(*currentP).attr.ArrayAttr.up=atoi(currentToken.Sem);
}
void CparseLL1::process22()
{
Push(2,END);
Push(1,FieldDecList);
Push(2,RECORD);
/*声明的类型部分为记录类型*/
(*currentP).kind.dec=RecordK;
saveP = currentP; /*压入当前节点,是为了处理完后回到当前节点,
主要是为了变量声明部分标识符部分在后面,考虑*/
PushPA(&((*currentP).child[0]));
}
void CparseLL1::process23()
{
Push(1,FieldDecMore);
Push(2,SEMI);
Push(1,IdList);
Push(1,BaseType);
TreeNode **t=PopPA();
currentP = newDecNode(); /*生成记录类型的下一个域,不添任何信息*/
temp=(&(currentP->kind.dec));
(*t) = currentP; /*若是第一个,则是record类型的子结点指向当前结点,
否则,是上一个纪录域声明的兄弟结点*/
PushPA(&((*currentP).sibling));
}
void CparseLL1::process24()
{
Push(1,FieldDecMore);
Push(2,SEMI);
Push(1,IdList);
Push(1,ArrayType);
TreeNode **t=PopPA();
currentP = newDecNode(); /*生成记录类型的下一个域,不添任何信息*/
(*t) = currentP; /*若是第一个,则是record类型的子结点指向当前结点,
否则,是上一个纪录域声明的兄弟结点*/
PushPA(&((*currentP).sibling));
}
void CparseLL1::process25()
{
/*后面没有记录类型的下一个域了,恢复当前纪录类型节点的指针*/
PopPA( );
currentP = saveP;
}
void CparseLL1::process26()
{
Push(1,FieldDecList);
}
void CparseLL1::process27()
{
Push(1,IdMore);
Push(2,ID);
/*纪录一个域中各个变量的语义信息*/
strcpy(currentP->name[currentP->idnum], currentToken.Sem);
currentP->idnum++;
}
void CparseLL1::process28()
{
}
void CparseLL1::process29()
{
Push(1,IdList);
Push(2,COMMA);
}
void CparseLL1::process30()
{
}
void CparseLL1::process31()
{
Push(1,VarDeclaration);
}
void CparseLL1::process32()
{
Push(1,VarDecList);
Push(2,VAR);
currentP=newVarNode(); /*生成一个标志变量声明的节点*/
TreeNode **t=PopPA();
(*t)=currentP;
PushPA(&((*currentP).sibling)); /*压入指向函数声明的指针*/
PushPA(&((*currentP).child[0])); /*压入指向第一个变量声明节点的指针*/
}
void CparseLL1::process33()
{
Push(1,VarDecMore);
Push(2,SEMI);
Push(1,VarIdList);
Push(1,TypeName);
TreeNode **t=PopPA();
currentP = newDecNode();/*建立一个新的声明节点,这里表示变量声明*/
(*t) = currentP; /*若是第一个节点,则变量声明的头指针指向它,
否则它是前一个变量声明的后继*/
PushPA(&((*currentP).sibling));
}
void CparseLL1::process34()
{
PopPA( );
}
void CparseLL1::process35()
{
Push(1,VarDecList);
}
void CparseLL1::process36()
{
Push(1,VarIdMore);
Push(2,ID);
strcpy(currentP->name[currentP->idnum], currentToken.Sem);
currentP->idnum++;
}
void CparseLL1::process37()
{
}
void CparseLL1::process38()
{
Push(1,VarIdList);
Push(2,COMMA);
}
void CparseLL1::process39()
{
}
void CparseLL1::process40()
{
Push(1,ProcDeclaration);
}
void CparseLL1::process41()
{
Push(1,ProcDecMore);
Push(1,ProcBody);
Push(1,ProcDecPart);
Push(2,SEMI);
Push(2,RPAREN);
Push(1,ParamList);
Push(2,LPAREN);
Push(1,ProcName);
Push(2,PROCEDURE);
currentP=newProcNode();
TreeNode **t=PopPA();
(*t)=currentP;
PushPA(&(currentP->sibling));
PushPA(&(currentP->child[2])); /*指向语句序列*/
PushPA(&(currentP->child[1])); /*指向函数的声明部分*/
PushPA(&(currentP->child[0])); /*指向参数声明部分*/
}
void CparseLL1::process42()
{ /*弹出过程节点的兄弟节点指针*/
//PopPA( ); /*为了统一处理,不能现在弹出*/
}
void CparseLL1::process43()
{
Push(1,ProcDeclaration);
}
void CparseLL1::process44()
{
Push(2,ID);
strcpy( currentP->name[0] , currentToken.Sem );
currentP->idnum++;
}
void CparseLL1::process45()
{
/*形参部分为空,弹出指向形参的指针*/
PopPA();
}
void CparseLL1::process46()
{
Push(1,ParamDecList);
}
void CparseLL1::process47()
{
Push(1,ParamMore);
Push(1,Param);
}
void CparseLL1::process48()
{
PopPA( );
}
void CparseLL1::process49()
{
Push(1,ParamDecList);
Push(2,SEMI);
}
void CparseLL1::process50()
{
Push(1,FormList);
Push(1,TypeName);
TreeNode **t=PopPA();
currentP=newDecNode();
/*函数的参数类型是值类型*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -