轉載請註明出處:https://blog.csdn.net/hhhhhhhhhhkkkkkkkkkk
demo 2 加乘計算器-有語義函數
#include<stdio.h>
#include"_lr1.h"
enum e_non
{
e_entry=-0xffff,
e_exp,
};
t_grammar g=
{
{
{e_entry,{e_exp},[](t_analyzer*ana) {ana->ref(0); },0},
{e_exp,{e_exp,'+',e_exp},[](t_analyzer*ana) {ana->ret(ana->get<float>(0)+ana->get<float>(2)); },0},
{e_exp,{e_exp,'*',e_exp},[](t_analyzer*ana) {ana->ret(ana->get<float>(0)*ana->get<float>(2)); },0},
{e_exp,{'i'},[](t_analyzer*ana) {ana->ret(1.0f); },0},
},
{
{'+',{1,e_ass_left}},
{'*',{2,e_ass_left}},
{'i',{3,e_ass_left}},
},
nullptr
};
int main(int argc, const char*argv[])
{
grammar_make_pri_ass(g);
print_grammar(g);
auto cluster = cluster_build(g, 0);
printf("---------------------\n");
print_cluster(cluster, g.sens);
printf("---------------------\n");
t_analyzer ana;
ana.analysis(std::vector<int>{ 'i','+','i','*','i',0 }, cluster, g, nullptr);
getchar();
return 0;
}
可以看到,在11-14行添加了語義函數後,能夠得到2.0這個 正確結果了(不要看最後一排結果,那裏已經塵歸塵,土歸土,什麼結果也沒有了)。
當然,爲了簡便,這裏的數字取的直接是1,如果想實現真正的數值計算,有兩個辦法:
1 如果只是單個數字,將
exp=i
改成
exp=0
exp=1
...
exp=9
2 如果是多位數,構造一個前端分析器(可以直接用手擼),將數字都轉成i,同時保存多位數在串中的範圍(其實這個就是爲什麼一般yacc之前還有一個lex的原因);
然後調用ana->range(0)得到當前輸入串的位置,再映射到上面保存的範圍,這樣可以從輸入串中讀取當前的終結符值,然後就可以轉成數字參與計算了。