您的位置:首页 > 其它

基于文法分析的表达式计算器的实现

2011-08-01 09:33 399 查看
  这个基于LL分析器的计算器是大三时上编译原理的一个作业。感觉是自己做过相对比较有深度的一个程序。第一次放出来跟大家分享。希望多多指教。

  这个计算器支持带括号的四则运算和乘方运算。具体实现过程如下:

  词法分析器:

  相关正则定义:

      DIGIT   [0-9]

      NUMBER {DIGIT}((.{DIGIT}+)|{DIGIT}*)

      DELIM  [ tn]

      OPERATOR [+|-|*|/|^|(|)|=]


  识别数值的DFA的状态转换图:



词法分析器的构造:

  因为要识别表达式中的负数(形如1+ -1),这个工作有两个做法,一个是在词法分析的过程中使得词法分析器可以识别负数。一个是词法分析器只识别正数,让语法分析器去识别负数还是减法运算符。前一种方法不是一个标准的词法分析程序可以完成的,因为它要引用上下文。至少向前看一个字符。这就是LL文法或LR(1)文法的范围了。所以使用第二种方案。这也是大多数情况下所采用的方案。

  文法分析器:

  计算器的功能:计划包括含括号的实数四则运算和乘方运算。同时还可以识别出负号。

  初期文法:



将上述文法消除左递归可得出下面的文法:注意乘方运算是具有右结合性的。而四则运算是左结合的。由于LL分析法本身的限制,要将一个非二义也非左递归的一个产生式:

进行转化(因为它有公共的左因子),使其可以用LL分析法进行分析。



计算出上述文法的FIRST集和FOLLOW集,如下:





  分析表的建立:因为空间原因,表项中只给出产生式的右部

id+-*/^()$
ETE’TE’TE’
E’+TE’-TE’
TFT’FT’FT’
T’*FT’/FT’
FN-NN
NMN’MN’
N’^N
MId(E)
  文法的分析表

  文法分析表建立完成之后,就可以开始写程序了。代码如下:

Code

 1/**///////////////////////////////////////////////////////////////////////////

 2//            ExpressionCalculator

 3//               Version 0.1

 4//            Powered by nankezhishi

 5//             All Right reserved.

 6//    本计算器支持带括号的四则、乘方运算。并可包含独立的负号。

 7/**///////////////////////////////////////////////////////////////////////////

 8#include "iostream"

 9#include "string"

10#include "cmath"

11using namespace std;

12

13//用于kind的值

14#define NUMBER 1000  

15#define MYERROR 1001

16#define END   1002

17//词法分析器的当前状态

18int state;

19//读取的内容

20string input;

21//字符串的长度

22int inputlength;

23//字符串读取的位置.

24int i = 0; 

25//词法分析器的返回值

26int returnvalue;

27//读取到数字时的值

28string strval;

29double yylval = 0;

30

31

32/**///////////////////////////////////////////////////////////////////////////

33//词法分析器

34/**///////////////////////////////////////////////////////////////////////////

35bool isdigit(char c){

36  return (c >= '0' && c <= '9')?true:false;

37}

38

39bool isoperator(char c){

40  return (c == '+'||c == '-'||c == '*'||c == '/'||c == '^'||c == '('||c == ')'||c == '=')?true:false;

41}

42

43//识别数字的DFA的状态转移函数

44int move(int state, char c){       

45  if (isdigit(c)){

46    return (state==0)?1:state;

47  }

48  else if (state == 1 && c == '.'){

49    return 2;

50  }

51  else if (( state == 2 || state == 1) && (c == ' ' || c == 'n' || c == 0 || isoperator(c))){

52    i--;                //操作符

53    return 3;             //接受

54  }

55  else

56    return 0;

57}

58

59int lexer(){

60  if (i == inputlength)

61    return END;

62  if (isoperator(input[i]))

63  {

64    i++;

65    return input[i-1];    //返回非数字运算符

66  }

67  int start = i;

68  for (;i < inputlength;)

69  {

70    state = move(state,input[i++]);

71    if (state == 0)

72      return MYERROR;

73    else if (state == 3)

74    {

75      strval = input.substr(start,i-start);

76      yylval = atof(strval.c_str());

77      return NUMBER;

78    }

79  }

80}

81

82

83/**///////////////////////////////////////////////////////////////////////////

84//语法分析器采用自上而下的分析方法.

85/**///////////////////////////////////////////////////////////////////////////

86void match(int t){

87  if (returnvalue == t)

88    returnvalue = lexer();

89  else{

90    cout << "EXPRESSION ERRON IN MATCH!" << endl;

91  }

92}

93

94double E();

95

96double M(){

97  double temp;

98  switch(returnvalue)

99  {

100  case NUMBER:

101    temp = yylval;

102    match(NUMBER);

103    return temp;

104  case '(':

105    match('(');

106    temp = E();

107    match(')');

108    return temp;

109  default:

110    cout << "EXPRESSION ERROR IN M()!" << endl;

111    return 0;

112  }

113}

114

115double N();

116

117double N_(){

118  switch(returnvalue)

119  {

120  case '+':

121  case '-':

122  case '*':

123  case '/':

124  case ')':

125  case END:

126    return 1;

127  case '^':

128    match('^');return N();

129  default:

130    cout << "EXPRESSION ERROR IN N_()!" << endl;

131    return 0;

132  }

133}

134

135double N(){

136  double m,n_;

137  switch(returnvalue)

138  {

139  case NUMBER:

140  case '(':

141    m = M();

142    n_ = N_();

143    return pow(m,n_);   //这里不可以写做pow(M(),N_())因为参数压栈的顺序是从右向左,这样就会先调用N_()而产生错误.

144  default:

145    cout << "EXPRESSION ERROR IN N()!" << endl;

146    return 0;

147  }

148}

149

150double F(){

151  switch(returnvalue)

152  {

153  case '-':

154    match('-');return -N();

155  case NUMBER:

156  case '(':

157    return N();

158  default:

159    cout << "EXPRESSION ERROR IN F()!" << endl;

160    return 0;

161  }

162}

163

164double T_(){

165  switch(returnvalue)

166  {

167  case '+':

168  case '-':

169  case ')':

170  case END:

171    return 1;     //对于乘法,这里要返回1.

172  case '*':

173    match('*');return F() * T_();

174  case '/':

175    match('/');return 1/(F() / T_());

176  default:

177    cout << "EXPRESSION ERROR IN T_()!" << endl;

178    return 0;

179  }

180}

181

182double T(){

183  switch(returnvalue)

184  {

185  case NUMBER:

186  case '-':

187  case '(':

188    return F() * T_();

189  default:

190    cout << "EXPRESSION ERROR IN T()!" << endl;

191    return 0;

192  }

193}

194

195double E_(){

196  switch(returnvalue)

197  {

198  case '+':

199    match('+');return T() + E_();

200  case ')':

201  case END:

202    return 0;

203  case '-':

204    match('-');return -(T() - E_());

205  default:

206    cout << "EXPRESSION ERROR IN E_()!" << endl;

207    return 0;

208  }

209}

210

211double E(){

212  switch(returnvalue)

213  {

214  case NUMBER:

215  case '-':

216  case '(':

217    return T() + E_();

218  default:

219    cout << "EXPRESSION ERROR IN E()!" << endl;

220    return 0;

221  }

222}

223

224int main(){

225  while ((cin >> input) && (inputlength = input.length()) > 0)

226  {

227    state = 0;

228    i = 0;

229    returnvalue = lexer();

230    cout << E() << endl;

231  }

232

233  /**///////////////////////////////////////////////////////////////////////////

234  //词法分析器测试程序

235  /**///////////////////////////////////////////////////////////////////////////

236  //while (i < inputlength)

237  //{

238  //  returnvalue = lexer();

239  //  if (returnvalue == NUMBER)

240  //  {

241  //    cout << yylval << endl;

242  //  }

243  //  else if (returnvalue == MYERROR)

244  //  {

245  //    cout << "表达式错误" << endl;

246  //  }

247  //  else

248  //    cout << (char)returnvalue << endl;

249  //}

250

251}


  可以看到,一个简单的计算器就有如此多的步骤。一个复杂的编译器的建立过程,即使有Yacc和Lex等的帮助,也是不容易的。

来源:南柯之石博客 作者:南柯之石 责编:豆豆技术应用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: