递归下降方式的运算解析器

原创 2006年05月31日 16:36:00

做了递归下降方式的运算解析器(C#),支持变量定义与运算 :

using System;

namespace ParserSpace
{
 /// <summary>
 /// 解析器类Parser
 /// </summary>
 public sealed class Parser
 {
  //Array for variables
  private double[] vars = new double[26];

  //令牌类型
  enum tokenEnum{NONE,DELIMITER,VARIABLE,NUMBER};

  //语法错误类型
  int SYNTAX=0;
  int UNBALPARENS=1;
  int NOEXP=2;
  int DIVBYZERO=3;

  //表达式完
  string EOE="/0";

  public string exp;  //表达式
  int expIdx;  //表达式当前指针
  public string token;//当前的令牌
  tokenEnum tokType; //当前的令牌类型

  //取得下一个令牌
  public  void getToken()
  {
    tokType=tokenEnum.NONE;
    token="";

    //检查表达式是否取完
    if(expIdx==exp.Length)
    {
     token=EOE;
     return;
    }

    //如果是空格则跳过
    while(expIdx<exp.Length&&(exp[expIdx]==' '))++expIdx;

    //是不是空格完了命令行也完成了
    if(expIdx==exp.Length)
    {
     token=EOE;
     return;
    }

    if(exp[expIdx]==':')   //如果冒号
    {
     token+=exp[expIdx];
     expIdx++;
     tokType=tokenEnum.DELIMITER;
    }
    else
     if (isDelim(exp[expIdx]))  //如果是操作符
     {
    token+=exp[expIdx];
    expIdx++;
    tokType=tokenEnum.DELIMITER;
     }
     else if((('a'<=exp[expIdx])&&('z'>=exp[expIdx]))||
       (('A'<=exp[expIdx])&&('Z'>=exp[expIdx])))
       //如果是变量
    {
       while(!isDelim(exp[expIdx]))
       {
        token+=exp[expIdx];
        expIdx++;
        if(expIdx>=exp.Length)
        break;
       }
       tokType=tokenEnum.VARIABLE;
      }
      else if (('0'<=exp[expIdx])&&('9'>=exp[expIdx]))  //如果是数字
     {
        while(!isDelim(exp[expIdx]))
        {
         token+=exp[expIdx];
         expIdx++;
         if(expIdx>=exp.Length)
        break;
        }
      tokType=tokenEnum.NUMBER;
     }
     else  //不可识别的终结表达式
     {
      token=EOE;
      return ;
     }
  }

  //如果是一个分隔符则返回真值
  private bool isDelim(char c)
  {
   if ((" +-/*%^=()".IndexOf(c)!=-1))
    return true;
   return false;
  }


  //解析器入口程序
  public double evaluate(string expstr)
  {
   double result=0.0;
   exp=expstr;
   expIdx=0;


   getToken();
   if(token.Equals(EOE))
    handleErr(NOEXP); //表示没有表达式

   //解析并计算表达式
   result=evalExp1();

   if(!token.Equals(EOE))
    handleErr(SYNTAX);

      return result;
  }

  //处理赋值
  private double evalExp1()
  {
   double result;
   int varIdx;
   tokenEnum ttokType;
   string temptoken;

   if (tokType==tokenEnum.VARIABLE)
   {
    //保存旧值
    temptoken=token;
    ttokType=tokType;

    //计算变量的索引
    varIdx=char.ToUpper(token[0])-'A';

    getToken();
    if (token.Equals('='))
    {
    putBack();  //返回当前的令牌
    //恢复老的令牌 (非赋值)
    token=temptoken;
    tokType=ttokType;
    }
    else
    {
     getToken(); //取得表达式的下一部分
     result=evalExp2();
     vars[varIdx]=result;
     return result;
    }
   }
   return evalExp2();
  }

  //两个项的加减
  private double evalExp2()
  {
   char op;
   double result;
   double partialResult;
   result=evalExp3();

   while((op=token[0])=='+'||op=='-')
   {
    getToken();
    partialResult=evalExp3();
    switch(op)
    {
      case '-':
       result=result-partialResult;
       break;
      case '+':
       result= result+partialResult;
       break;

    }
   }
   return result;
  }

  //两个项的乘或除
  private double evalExp3()
  {
   char op;
   double result;
   double partialResult;

   result=evalExp4();

   while((op=token[0])=='*'||op=='/'||op=='%')
   {
    getToken();
    partialResult=evalExp4();
    switch(op)
    {
      case '*':
      result=result * partialResult;
      break;
      case '/':
      if (partialResult==0.0)
        handleErr(DIVBYZERO);
      result=result / partialResult;
      break;
      case '%':
      if(partialResult==0.0)
        handleErr(DIVBYZERO);
      result= result % partialResult;
      break;
    }
   }
   return result;
        }

  //指数运算
  private double evalExp4()
  {
   double result;
   double partialResult;
   double ex;
   

   result=evalExp5();

   if(token.Equals('^'))
   {
     getToken();
     partialResult=evalExp4();
     ex=result;
     if(partialResult==0.0)    //指数为零
     {
      result=1.0;
     }
     else
    for(int t=(int)partialResult-1;t>0;t--)
      result=result*ex;
   }
   return result;
  }

  //计算一元的加减运算
  private double evalExp5()
  {
   double result;
   string op;
   op="";
   if((tokType==tokenEnum.DELIMITER)&& token.Equals('+')||token.Equals('-'))
   {
    op=token;
    getToken();
   }
   result=evalExp6();

   if(op.Equals('-'))
     result=-result;
   return result;
  }

  //处理加括号的表达式
  private double evalExp6()
  {
   double result;

   if(token.Equals('('))
   {
     getToken();
     result=evalExp2();
     if(!token.Equals(')'))
     handleErr(UNBALPARENS);
     getToken();
   }
   else
    result=atom();
   return result;
  }

  //读取数字
  private double atom()
  {
   double result=0.0;
 
   switch(tokType)
   {
    case tokenEnum.NUMBER:
            try{
    result=Double.Parse(token);
   }
   catch(FormatException exc)
   {
     handleErr(SYNTAX);
   }
            getToken();
   break;
    case tokenEnum.VARIABLE:
   result=findVar(token);
   getToken();
   break;
    default:
   handleErr(SYNTAX);
    break;
   }
   return result;
  }

  //处理错误
  private void handleErr(int error)
  {
   string[] err={
     "语法错误",
     "括号缺失(不对称)",
     "没有表达式",
     "被除数为零"
   };
   throw new ParserException(err[error]);
  }

  //返回变量的值
  private double findVar(string vname)
  {
   if ((vname[0]>='a')&&(vname[0]<='Z'))
   {
    handleErr(SYNTAX);
    return 0.0;
   }
   return vars[char.ToUpper(vname[0])-'A'];
  }

  //返回令牌到输入字符串流中
  private void putBack()
  {
   if (token==EOE)return;
   for (int i = 0; i < token.Length; i++)
    expIdx--;
  }

  public Parser()
  {
  }
 }
}

递归下降分析法(编译原理)

递归向下分析法C语言实现
  • u011889952
  • u011889952
  • 2015年03月23日 19:15
  • 7342

递归下降分析

递归下降分析算法,也称为预测分析优点:1).分析高效(线性时间) 2).容易实现(方便手工编码) 3).错误定位和诊断信息准确 4).被很多开源和商业的编译器所采用(如GCC 4.0, LLVM...
  • shaguabufadai
  • shaguabufadai
  • 2017年05月12日 12:58
  • 685

递归下降语法分析实验

一、实验目的通过设计、开发一个高级语言的递归下降语法分析程序,实现 对词法分析程序所提供的单词序列进行语法检查和结构分析,加 深对相关课堂教学内容的理解,提高语法分析方法的实践能力。二、实验要求(...
  • SY_Yu
  • SY_Yu
  • 2016年10月30日 09:02
  • 3952

编译原理-递归下降分析器

编译原理-简单的递归下降语法分析器LL(1)在网上看了很多篇关于递归下降分析器的博文,均没有满意的,一是所写的程序不对、二是解释的不够清楚。所以想自己写一篇,顺便总结一下所学。递归下降分析法递归下降分...
  • Jiaxin520
  • Jiaxin520
  • 2017年12月08日 00:10
  • 206

完整的词法分析器和使用递归下降分析法的语法分析程序 java

  • 2010年06月18日 17:58
  • 339KB
  • 下载

递归下降分析法的简单例子的c语言实现

我们举的简单例子是 G[s]: S→a |∧| (T) T→T, S | S 转化为LL1文法 S →a |∧| (T) T →ST' T'→,ST'| ε c语言代码实现  ...
  • zhouyelihua
  • zhouyelihua
  • 2012年04月08日 20:23
  • 4909

递归下降语法分析

  • 2013年04月29日 13:20
  • 1.2MB
  • 下载

递归下降分析法

递归下降分析法1.             实验题目:  递归下降分析法2.             实验目的:                  1 掌握递归下降分析法的基本原理       2 掌...
  • pulybuffer
  • pulybuffer
  • 2007年11月23日 09:24
  • 5171

递归下降分析法的实现

  • 2013年12月01日 16:50
  • 3KB
  • 下载

编译原理——语法分析器(递归下降分析法 )

  • 2010年05月05日 22:53
  • 39KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:递归下降方式的运算解析器
举报原因:
原因补充:

(最多只允许输入30个字)