MiniBasic解析器实现二

上文给出实现的头文件以及演示界面,朋友拿去我这个去参赛,竟然入了决赛,汗一个先,现在给它的实现文件。注释完整,在此基础上大家可以实现自己的迷你脚本解析器。如有问题不要找我也不用告诉我,我是喜新厌旧的人,懒得再动它了。

转载请注明出处,你可以任意的强*它,代码可以按你的爱好去修改,一句话:任你为所欲为吧。

#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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值