- 论坛徽章:
- 0
|
本帖最后由 Solidus 于 2010-03-12 08:06 编辑
回复 cjaizss
非也。
扫描并非影响文法识别的最大因素。
所以,我想说的其实并不是只扫描两端,而是 ...
xyfree 发表于 2010-03-10 16:18 ![]()
我不太理解你这种方法如何能分别应用在提取词素和语法单元上,
如果以词法分析为例,“两端”这个说法本身就有问题,一个最简单的例子,我需要过滤掉空行,那么空行的意思是[ \t]*(\r)*\n,而非空行就是[ \t]*.+(\r)*\n,这里面可能还牵扯到非空行以xx开头的注释,也许要过滤掉。
如果以语法分析为例,“两端”更难判定,以C语言这种上下文相关语言为例,至少同一个范围有三个独立的符号表协作,你没办法在某个点上独立的判断出来符号X在当前scope下的词法值是什么,如果必须不依赖符号表建立完整的语法树,只能设定ID这一个词法值,那么就得靠回朔,比如
typedef int x_t;
void test()
{
x_t = 3;
}
不依赖上文typedef,在这个block里的x_t毫无意义,如果词法分析模块不查表,你在x_t = 3这里根本就看不到错误,如果还需要得到正确的语法树,那么文法就必须把DECL写成DECL : ID ID....; 这类文法在分析C语言中就已经得靠回朔了(例如LL(K>1), LR(K>1), GLR, Backtracking-LR等等),否则就是冲突,现在无回朔的例如YACC(LALR(1))什么的东西都是靠一个近似的BNF然后自己手工分析去,例如对一个符号至少有俩可能的词法值,TYPE_ID和ID,之后依赖符号表确定到底是什么。
第一个例子说明,对于一个状态机,必须从起始状态经过中间状态才能知道哪里是结尾,而语法这个例子的意思是即使不带任何语义分析的,只提取语法结构的parser来说,也是一个协作系统,即使走过中间状态都不足以分析清楚什么是什么,都得借助额外的数据库辅助,所以独立的提取单元可能是个非常麻烦的事情,即使可以也需要比这种按部就班的预测分析慢得多得多。
最后就是,从我个人经验上看,分析部分所占用的时间比重不是很大,更多的是语义处理,查表,优化等等乱七八糟的事情。虽然理论上分析很重要,但是在工程中不论是代码量还是占用的CPU时间都很小。
PS:我不认为人类识别单词是靠两端,而是人类大脑中有个启发式的经年累月积累下的符号表,匹配算法现在也无从知晓,输入即可以是一个词也可以是一个短语和一个句子,然后自己脑补,精分~~,当然,人类这种脑补行为本身就是个错误率极高的事情,换句话说,之所以有计算机这类东西一大部分原因就是希望借助计算机无差错的重复去做有点傻的事情,而不是让一帮聪明的人高效的去做可能做错的事情,至少计算机的输入输出是可以证明的。 |
|