下面是处理好的正则文法:
A → a | e | i | o | u
MOD → ga | ge | gi | go | gu
BA → ba | be | bi | bo | bu
DA → da | de | di | do | du
LA → la | le | li | lo | lu
NAM → {all names}
PREDA → {all predicates} | PREDA PREDA
<sentence> → <statement> | <predclaim>
<predclaim> → <predname> BA <preds> | DA <preds>
<preds> → <predstring>
<predname> → LA <predstring> | NAM
<predstring> → PREDA | <predstring> A <predstring>
<predverb> → <predname> <verbpred>
<statement> → <predverb> <predname> | <predverb>
<verbpred> → MOD <predstring>
根据这个文法就可以快速的判断语句的正确性了。先将输入的所有字符串转换为单词(包括谓词和小单词)或名称,可根据最后一个字母是否元音来判断是单词还是名称,如果是名称就直接转为NAM,如果是单词则需按上面的文法查表(有不用查表的小技巧,详见代码)。整个句子都转换完成后,就要按照顺序对符号进行推导,过程如下:
PREDA → PREDA PREDA
<predstring> → <predstring> PREDA
<predstring> → PREDA
<predname> → NAM
<predname> → LA <predstring>
<verbpred> → MOD <predstring>
<preds> → <predstring> A <predstring>
<preds> → <predstring>
<predclaim> → <predname> BA <preds> | DA <preds>
<predverb> → <predname> <verbpred>
<statement> → <predverb> <predname> | <predverb>
<predclaim> → <sentence>
<statement> → <sentence>
如果最后能推得sentence,说明句法是正确的,否则就是错误的。推导的方法其实就是对动态数组进行插入和删除的操作:如果一个符号可以直接推导出另一个符号,则直接改写为推导出的符号;如果一个符号和前缀一起能推导出另一个符号,就将前缀删除,当前符号改写为推导出的符号;后缀的情况还有前后缀一起推导的情况也是一样。具体算法详见代码的注释,非常详细。
程序中状态转换表的顺序与上述推导顺序相同(某些次序可以颠导,不影响结果的正确性,可能程序中略有不同)。符号枚举类型中的符号名为符号的缩写,对应如下:
UN: 未知/出错
PS: predstring
P: preds
PN: predname
SE: sentence
VP: verbpred
PV: predverb
PC: predclaim
ST: statement
其它符号名与题目给出的相同。
本文导航
- 第1页: 首页
- 第2页: Loglan 语言分析
- 第3页: 下面是处理好的正则文法
- 第4页: Loglan问题解决方案