上文给出实现的头文件以及演示界面,朋友拿去我这个去参赛,竟然入了决赛,汗一个先,现在给它的实现文件。注释完整,在此基础上大家可以实现自己的迷你脚本解析器。如有问题不要找我也不用告诉我,我是喜新厌旧的人,懒得再动它了。
转载请注明出处,你可以任意的强*它,代码可以按你的爱好去修改,一句话:任你为所欲为吧。
#include "LineNode.h"
LineNode::LineNode(int auto_number)
{
m_auto_number = auto_number;
m_auto_line_number =1;
pHead=0;
}
LineNode::~LineNode()
{
Clear();
pHead=0;
}
void LineNode::Clear()
{
m_auto_line_number =1;
pLNode pNode =pHead;
pLNode pTmpNode;
while(pNode)
{
pTmpNode = pNode->next;
free(pNode);
pNode= pTmpNode;
}
}
pLNode LineNode::AllocNode()
{
pLNode pNode =(pLNode)malloc(sizeof(LNode));
pNode->LineNumber =0;
pNode->CType =EUnKnown;
pNode->OType =ESet;
pNode->LeftValue.is_const =1;
pNode->LeftValue.value =0;
pNode->RightValue.is_const =1;
pNode->RightValue.value =0;
pNode->RightValue.is_const =1;
pNode->ResultValue.is_const =0;
pNode->Commands[0] ='/0';
//将新分配的节点放到链表的最后一个节点
if(0==pHead)
{
pNode->prior =0;
pHead =pNode;
}
else
{
pLNode pTempNode =pHead;
while(0!=pTempNode->next)
{
pTempNode= pTempNode->next;
}
pTempNode->next = pNode;
pNode->prior =pTempNode;
}
pNode->next =0;
return pNode;
}
void LineNode::LoadCommandFromFile(const char *sFileName)
{
FILE *fp =fopen(sFileName,"r");
if(NULL==fp)
return ;
char sBuffer[2048];
while(0 !=ReadLine(fp,sBuffer,2048))
{
LocalInput(sBuffer);
}
fclose(fp);
}
void LineNode::SaveCommandToFile(const char *sFileName)
{
FILE *fp =fopen(sFileName,"w");
if(NULL==fp)
return ;
pLNode pNode =pHead;
while(pNode)
{
fprintf(fp,"%s /n",pNode->Commands);
pNode= pNode->next;
}
fclose(fp);
}
void LineNode::PrintCommands(FILE *fp)
{
pLNode pNode =pHead;
while(pNode)
{
if(NULL==fp)
printf("%s/n",pNode->Commands);
else
fprintf(fp,"%s/n",pNode->Commands);
pNode= pNode->next;
}
}
int LineNode::ParseLineNumber(const char *sBuffer,int *endPos)
{
int start,end;
char int_v[128];
const char *pStartPtr = sBuffer;
start =0;
//找到第一个不为空的字符
while('/0' != *sBuffer)
{
if(BLANK_CHAR !=*sBuffer)
break;
sBuffer++;
start++;
++(*endPos);
}
//找到第一个为空的字符
end =start;
while('/0' != *sBuffer)
{
if(BLANK_CHAR ==*sBuffer)
break;
end++;
sBuffer++;
++(*endPos);
}
//取数字行号
if(end>start)
{
memset(int_v,'/0',sizeof(int_v));
memcpy(int_v,pStartPtr+start,end-start);
memset(int_v+end-start+1,1,'/0');
return atoi(int_v);
}
return 0;
}
CommmandType LineNode::ParseCommand(const char *sBuffer,int *endPos)
{
int start,end;
char cmd_v[128];
const char *pStartPtr = sBuffer;
start =0;
//找到第一个不为空的字符
while('/0' != *sBuffer)
{
if(BLANK_CHAR !=*sBuffer)
break;
sBuffer++;
start++;
++(*endPos);
}
//找到第一个为空的字符
end =start;
while('/0' != *sBuffer)
{
if(BLANK_CHAR ==*sBuffer)
break;
end++;
sBuffer++;
++(*endPos);
}
//取数字行号
if(end>start)
{
memset(cmd_v,'/0',sizeof(cmd_v));
memcpy(cmd_v,pStartPtr+start,end-start);
memset(cmd_v+end-start+1,1,'/0');
if(strcmp("LET",cmd_v)==0)
return ELET;
else if(strcmp("PRINT",cmd_v)==0)
return EPRINT;
else if(strcmp("IF",cmd_v)==0)
return EIF;
else if(strcmp("GOTO",cmd_v)==0)
return EGOTO;
else if(strcmp("STOP",cmd_v)==0)
return ESTOP;
}
return EUnKnown;
}
//返回 指定符号的位置,如果返回0表未找不到指定符号
int LineNode::PosChar(const char *sBuffer,char ch)
{
int i=0;
while('/0' != *sBuffer)
{
if(ch == *sBuffer)
return i;
sBuffer++;
i++;
}
return -1;
}
void LineNode::ParseExpression(char *sBuffer,int *endPos,pLNode pNode)
{
int start,end,ret;
char ch;
start =0;
//找到第一个不为空的字符
while('/0' != *sBuffer)
{
if(BLANK_CHAR !=*sBuffer)
break;
sBuffer++;
start++;
++(*endPos);
}
end =start;
//找到第一个为空的字符
switch(pNode->CType)
{
case ELET: /*赋值语句*/
{
//X
pNode->ResultValue.is_const = 0;
pNode->ResultValue.value = *sBuffer-'A';
sBuffer+=2; //跳过=号
ret =PosChar(sBuffer,'+');
if(ret<0) //如果找不到 "+" 号
{
/*赋值,LET X=Y X:ResultValue Y:LeftValue */
pNode->OType =ESet;
if(IS_CONST_CHAR(*sBuffer))
{
pNode->LeftValue.is_const = 1;
pNode->LeftValue.value = atoi(sBuffer);
}
else
{
pNode->LeftValue.is_const = 0;
pNode->LeftValue.value = *sBuffer - 'A';
}
}
else
{
/*相加,LET X=Y+Z X:ResultValue Y:LeftValue Z:RightValue */
pNode->OType =EAdd;
//Y
if(IS_CONST_CHAR(*sBuffer))
{
ch = *(sBuffer+ret);
*(sBuffer+ret) ='/0';
pNode->LeftValue.is_const = 1;
pNode->LeftValue.value = atoi(sBuffer);
*(sBuffer+ret) =ch;
}
else
{
pNode->LeftValue.is_const = 0;
pNode->LeftValue.value = *sBuffer - 'A';
}
// +
sBuffer +=ret;
sBuffer++; //跳过 "+" 号
// Z
if(IS_CONST_CHAR(*sBuffer))
{
pNode->RightValue.is_const = 1;
pNode->RightValue.value = atoi(sBuffer);
}
else
{
pNode->RightValue.is_const = 0;
pNode->RightValue.value = *sBuffer - 'A';
}
}
}
break;
case EPRINT: /*打印*/
{
pNode->ResultValue.is_const =0;
pNode->ResultValue.value =*sBuffer-'A';
}
break;
case EGOTO: /*跳转*/
{
if(IS_CONST_CHAR(*sBuffer)) //Line number ,Goto expression
{
pNode->ResultValue.is_const =1;
pNode->ResultValue.value =atoi(sBuffer);
}
else
{
pNode->ResultValue.is_const = 0;
pNode->ResultValue.value = *sBuffer-'A';
}
}
break;
case EIF: /*判断语句*/
{
ret =PosChar(sBuffer,'>');
if(ret>=0)
{
/*大于,IF X>Y X:LeftValue Y:RightValue */
//X
if(IS_CONST_CHAR(*sBuffer))
{
ch = *(sBuffer+ret);
*(sBuffer+ret) ='/0';
pNode->LeftValue.is_const = 1;
pNode->LeftValue.value = atoi(sBuffer);
*(sBuffer+ret) =ch;
}
else
{
pNode->LeftValue.is_const = 0;
pNode->LeftValue.value = *sBuffer-'A';
}
//跳过>号
sBuffer +=ret;
sBuffer++;
//Y
if(IS_CONST_CHAR(*sBuffer))
{
pNode->RightValue.is_const =1;
pNode->RightValue.value =atoi(sBuffer);
}
else
{
pNode->RightValue.is_const = 0;
pNode->RightValue.value = *sBuffer-'A';
}
}
}
break;
case ESTOP:
{
}
break;
}
}
CommmandType LineNode::ParseInput(char *sBuffer)
{
pLNode pNode;
CommmandType cType;
int length;
int len; //当前解释的开始位置
cType = EUnKnown;
length = strlen(sBuffer);
pNode = AllocNode();
len = 0;
strcpy(pNode->Commands,sBuffer);
//解析行号
pNode->LineNumber = ParseLineNumber(sBuffer+len,&len);
if(0==pNode->LineNumber)
{
free(pNode);
return cType;
}
//解析命令
cType =ParseCommand(sBuffer+len,&len);
pNode->CType = cType;
//解析表达式
ParseExpression(sBuffer+len,&len,pNode);
return cType;
}
void LineNode::SetAutoNumber(int auto_number)
{
m_auto_number = auto_number;
}
bool LineNode::LocalInput(const char *sBuf)
{
if(m_auto_number) //如果是自动填充行号
{
char sBuffer[2048];
sprintf(sBuffer,"%d ",m_auto_line_number);
printf("%d ",m_auto_line_number);
strcpy(sInputBuffer,sBuffer);
strcat(sInputBuffer,sBuf);
m_auto_line_number++;
}
else //手工输写行号
{
strcpy(sInputBuffer,sBuf);
}
switch(ParseInput(sInputBuffer))
{
case ELET:
case EPRINT:
case EGOTO:
case EIF:
case ESTOP:
return true;
case EUnKnown:
return false;
default:
return true;
}
}
bool LineNode::Input()
{
if(m_auto_number) //如果是自动填充行号
{
char sBuffer[2048];
sprintf(sBuffer,"%d ",m_auto_line_number);
printf("%d ",m_auto_line_number);
strcpy(sInputBuffer,sBuffer);
gets(sBuffer);
strcat(sInputBuffer,sBuffer);
m_auto_line_number++;
}
else //手工输写行号
{
gets(sInputBuffer);
}
switch(ParseInput(sInputBuffer))
{
case ELET:
case EPRINT:
case EGOTO:
case EIF:
case ESTOP:
return true;
case EUnKnown:
return false;
default:
return true;
}
}
bool LineNode::ExpressionResult(Var *leftVar,Var *rightVar)
{
return ( GetValue(leftVar) > GetValue(rightVar) );
}
void LineNode::PrintResult(Var *var,FILE *fp)
{
if(NULL==fp)
printf("%c=%d/n",var->value+'A',GetValue(var));
else
fprintf(fp,"%c=%d/n",var->value+'A',GetValue(var));
}
int LineNode::GetValue(Var *var)
{
switch(var->is_const)
{
case 1: //常量
return (var->value);
case 0: //变量
return (var->value<VAR_ARRY_MAX) ? Var_Values[var->value] : 0;
}
return 0;
}
void LineNode::SetValue(Var *var,int value)
{
switch(var->is_const)
{
case 0: //变量
{
if(var->value<VAR_ARRY_MAX)
Var_Values[var->value]= value;
}
break;
}
}
pLNode LineNode::GotoLine(Var *var)
{
int line_number;
if(1 ==var->is_const) //常量
{
line_number = var->value;
}
else
{
if(var->value<VAR_ARRY_MAX)
line_number = Var_Values[var->value];
else
return 0;
}
pLNode pNode =pHead;
while(pNode)
{
if(pNode->LineNumber == line_number)
return pNode;
pNode = pNode->next;
}
return 0;
}
void LineNode::Caculate()
{
//自动初始化所有变量
for(int i=0; i<VAR_ARRY_MAX; i++)
Var_Values[i]=0;
printf("/n Result List:/n");
//逐条命令解析
pLNode pNode =pHead;
while(pNode)
{
switch(pNode->CType)
{
case ELET: /*赋值语句*/
{
switch(pNode->OType)
{
case ESet: /*赋值,LET X=Y X:ResultValue Y:LeftValue */
{
SetValue(&pNode->ResultValue, GetValue(&pNode->LeftValue));
}
break;
case EAdd: /*相加,LET X=Y+Z X:ResultValue Y:LeftValue Z:RightValue */
{
SetValue(&pNode->ResultValue,GetValue(&pNode->LeftValue) + GetValue(&pNode->RightValue));
}
break;
}
pNode= pNode->next;
}
break;
case EPRINT: /*打印*/
{
PrintResult(&pNode->ResultValue);
pNode= pNode->next;
}
break;
case EGOTO: /*跳转*/
{
pNode = GotoLine(&pNode->ResultValue);
}
break;
case EIF: /*判断语句*/
{
pNode = ExpressionResult(&pNode->LeftValue,&pNode->RightValue) ? pNode : pNode->next ;
pNode= pNode->next;
}
break;
case ESTOP: /*停止执行*/
return ;
break;
case EUnKnown:/*未知,错误指令*/
return;
default:
return ;
}
}
}
//从文件中取一行数据到Buffer中
int LineNode::ReadLine(FILE *fp, char *lineBuffer, int maxLength)
{
int size = 0;
char ch;
memset(lineBuffer, 0, maxLength);
while( !feof( fp ) )
{
if( size < maxLength )
{
ch = fgetc( fp );
switch(ch)
{
case 0x0A: // 支持windows和Linux换行符
case EOF: //遇到文件结束符
{
lineBuffer[size] = 0;
return size;
}
default:
{
lineBuffer[size] = ch;
size++;
}
break;
}
}
}
return size;
}
测试用例:
// MiniBasic.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include "LineNode.h"
int main(int argc, char* argv[])
{
LineNode NodeList;
char cmd[1];
char file_name[512];
const char *pComment ="/n Welcome to MiniBasic /n "
" Make sure there is no more black around of oprator ( '+', '=' )/n"
" Please select ! /n "
" 1. Load command from file with line number /n "
" 2. Load command from file no line number /n "
" 3. Input commmand manual /n "
" 4. Print latest commands /n "
" 5. Clear screen /n "
" 6. Quit /n ";
do
{
printf("%s",pComment);
scanf("%c",cmd);
if('6' ==cmd[0])
break;
switch(cmd[0])
{
case '1':
{
printf("Please input file name:");
scanf("%s",file_name);
NodeList.SetAutoNumber(0);
NodeList.LoadCommandFromFile(file_name);
printf("/n Command List:/n");
NodeList.PrintCommands();
NodeList.Caculate();
}
break;
case '2':
{
printf("Please input file name:");
scanf("%s",file_name);
NodeList.SetAutoNumber(1);
NodeList.LoadCommandFromFile(file_name);
printf("/n Command List:/n");
NodeList.PrintCommands();
NodeList.Caculate();
}
break;
case '3':
{
NodeList.SetAutoNumber(1);
while(NodeList.Input())
;
NodeList.Caculate();
}
break;
case '4':
{
printf("/n Command List:/n");
NodeList.PrintCommands();
}
break;
case '5':
{
system( "CLS");
}
break;
}
}
while(0);
return 0;
}
code.txt文件内容:
1 LET A=10
2 LET I=0
3 LET X=I+I
4 LET T=1
5 LET X=X+T
6 PRINT X
7 LET T=1
8 LET I=I+T
9 IF A>I
10 GOTO 3
11 STOP