Java问题请教
时间:2014-02-08
来源:互联网
这是一个recursive-descent parser,就是入一条算式就可以得到答案。这个程式当中也配合先乘除后加减的原则。
比如算式是10-3*2,那这些数字跟operator是在程式中怎样运作的?
sample code在
http://www.mhprofessional.com/getpage.php?c=computing_downloads.php&cat=112#S-U
下面的 The Art of Java一个项目。下载后打开chapter02的file就可以看到。
谢谢大家
作者: sense2000 发布时间: 2014-02-08
如果细心啲睇, 可睇得出每一个 evalExpN 都代表一个 expression (production rule).
Expression 用来描述一堆 tokens 的组成.
Grammar 就系整个 language 的语法描述.
例如, chap 2 嗰个 grammar 的简化版用 BNF 描述出来好似系咁的:
exp1 = variable '=' exp2
exp2 = exp3 ('+' | '-') exp3
exp3 = exp4 ('*' | '/' | '%') exp4
exp4 = exp5 '^' exp4
exp5 = ('+' | '-') exp6
exp6 = '(' exp2 ')' | atom
atom = number | variable
number = a valid result of Double.parseDouble(token)
variable = [a-z]
每一个 expression 被 evaluate 时都会因应个 operator 而作相应运算. 各 operator 的先后次序, 可由上 grammar 看出的先后次序:
1. -9
2. (-9)^(2*2/3%4)
3. ((-9)^(2*2/3%4)) + (1) - (2)
4. a=((-9)^(2*2/3%4)) + (1) - (2)
要完全理解 recursive decent parser 可能要认识当中涉及的资料结构同背后的思想.资料结构由最基本的字元, 英文字, 数字, 空白, token, delimitor 等等.背后的思想如 EBNF grammar, production rule, procedure(我估即系 expression?), regular expression 等等.
如果简化个 program 你理唔理解到丫?
例如只做加减运算, 无变数定义和代入.
明白后再渐渐加入其它功能, 再逐中理解.
本人已经花了几天的时间,但是还未能了解这个程式怎样去执行,还望各位朋友能够简单地解释一下。
这是一个recursive-descent parser,就是入一条算式就可以得到答案。这个程式当中也配合先乘除后加减的原则。
比如 ...
作者: a8d7e8 发布时间: 2014-02-08
比如说 2+3
1 getToken拿到 ’2‘ 这个token及token type
2 之后result这个值是从方法之中的方法代入。由於第一个token不是( 及 ),所以就移动至atom()。
3 在atom()中,把这个 ’2‘ 的格式由本来的String变成 double;
4 之后再进行getToken(),拿到 ’+‘ 这个token及其token type;
5 由於是加号,由5-3的方法均不适用,result(就是2)就回到方法2
6 根据方法2,
while((op = token.charAt(0)) == '+' || op == '-') {
getToken();
partialResult = evalExp3();
switch(op) {
case '-':
result = result - partialResult;
break;
case '+':
result = result + partialResult;
break;
}
由於是 + 号,故此再进行getToken(),拿到3这个token;
7 之后再把3变成double type及代入partialResult;
8 再进行2+3,并将之代入result,得出答案。
作者: sense2000 发布时间: 2014-02-08
1. 根据getToken()的number,
else if(Character.isDigit(exp.charAt(expIdx))) { // is number
while(!isDelim(exp.charAt(expIdx))) {
token += exp.charAt(expIdx);
expIdx++;
if(expIdx >= exp.length()) break;
}
tokType = NUMBER;
}
如果连着是数字而不是operator的话,就会不断loop这一部分,第一及第二token就会加起来成为一个token。这里先拿到1,再loop一次,拿到0,由於是String type,1+0就变成10;再在atom()把这个token变成double type;
2之后在atom()里的getToken()拿到 + 这个token;
3 由於方法5到方法3不适用,就回到方法2;
4 在方法2确定是 + , 就执行 getToken(), 拿到2这个token;
5 同样,在代入partialResult过程中,回到atom(),并把2变成double type,代入atom()的result;
6 执行atom()中的getToken(),得到*这个token;
7 再回到方法3,却认是*,就执行方法3的getToken(),得到3这个token;
8 在方法3的代入partial result过程中,在atom()把3变成double type;
9 执行atom的getToken(), 由於
// Check for end of expression.
if(expIdx == exp.length()) {
token = EOE;
return;
expIdx跟exp.length相等,getToken()终止运作;
10 返回方法3,进行 2*3,代入方法3的result,再把之代入方法2的partial result;
11 进行10+6, 代入方法2的result, 得出答案。
作者: sense2000 发布时间: 2014-02-08
但无论如何,多谢你悉心ge提点~~~

作者: sense2000 发布时间: 2014-02-08
你只要识得一层一层由地下开始起楼, 就可以起到摩天大楼.
不知道我的理解对不对。
但无论如何,多谢你悉心ge提点~~~

作者: a8d7e8 发布时间: 2014-02-08
+
evalExp3 -- evalExp4 -- evalExp5 -- evalExp6 -- atom -- 2
*
evalExp4 -- evalExp5 -- evalExp6 -- atom -- 3
作者: form5 发布时间: 2014-02-08
+
evalExp3
result = evalExp3()
if op is '+' or '-'
partialResult = evalExp3()
switch(op)
case '-': result = result - partialResult
case '+': result = result + partialResult
作者: form5 发布时间: 2014-02-08
evalExp2 -- evalExp3 -- evalExp4 -- evalExp5 -- evalExp6 -- atom -- 10
作者: form5 发布时间: 2014-02-08
evalExp2 -- evalExp3
+
evalExp3=>evalExp2
result = evalExp3()
if op is '+' or '-'
partialResult = evalExp3()
switch(op)
case ...
作者: form5 发布时间: 2014-02-08
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28