LL(1)文法求算數表達式的值
遞歸子程式法
分析過程:
表達式文法G[E]:
E->E+T|E-T|T
T->T*F|T/F|T%F|F
F->N^F|N
N->(E)|NUM|+NUM|-NUM
消除左遞歸、左公共因子
E ->TE'
E'->+TE'|-TE'|ε
T ->FT'
T'->*FT'|/FT'|%FT'|ε
F ->NF'
F'->^F|ε
N->(E)|NUM|+NUM|-NUM
FIRST集和FOLLOW集
LL(1)分析表
(應該沒錯吧……表示昨天剛考完試……)
(嗯。。我承認我抄。。咳咳。。借鑒了這份代碼http://ideone.com/o2Ag4。。還是炮姐寫的好。。)
#include
#include
enum SYM_KIND { // 符号類型
SYM_NUM, // num
SYM_ADD, // +
SYM_SUB, // -
SYM_MUL, // *
SYM_DIV, // /
SYM_MOD, // %
SYM_POW, // ^
SYM_LBR, // (
SYM_RBR, // )
SYM_END, // '\0'
SYM_ERR // 其他不合法符号
};
enum ERR_KIND { // 狀态
ERR_OK,
ERR_INVALID_CHAR,
ERR_NO_OPERATOR,
ERR_BR_NOT_MATCH,
ERR_NO_NUM,
ERR_END
};
char expr[]; // 表達式
int pos; // 讀取到表達式的位置
double val;
ERR_KIND err;
void F();
void E();
void NUM()
{
val = ;
while (expr[pos] <= '' && expr[pos] >= '')
{
val = val * + expr[pos] - '';
pos++;
}
if (expr[pos] == '.')
{
pos++;
double eo = 0.1;
while (expr[pos] <= '' && expr[pos] >= '')
{
val += (expr[pos] - '') * eo;
eo *= 0.1;
pos++;
}
}
}
SYM_KIND get_sym() // 讀取一個單詞
{
char ch = expr[pos++];
while (ch == ' ' || ch == '\t') // 忽略空格
ch = expr[pos++];
if (ch <= '' && ch >= '')
{
pos--;
NUM();
return SYM_NUM;
}
else if (ch == '+') return SYM_ADD;
else if (ch == '-') return SYM_SUB;
else if (ch == '*') return SYM_MUL;
else if (ch == '/') return SYM_DIV;
else if (ch == '%') return SYM_MOD;
else if (ch == '^') return SYM_POW;
else if (ch == '(') return SYM_LBR;
else if (ch == ')') return SYM_RBR;
else if (ch == '\0')
{
err = ERR_END;
return SYM_END;
}
err = ERR_INVALID_CHAR;
return SYM_ERR;
}
void N() // N->(E)|NUM|+NUM|-NUM
{
if (err != ERR_OK) return ;
SYM_KIND kind = get_sym();
if (kind == SYM_LBR)
{
E();
if (err == ERR_END)
{
err = ERR_BR_NOT_MATCH;
}
else if (err == ERR_OK)
{
kind = get_sym();
if (kind != SYM_RBR)
err = ERR_BR_NOT_MATCH;
}
}
else if (kind == SYM_ADD)
{
kind = get_sym();
if (kind != SYM_NUM)
{
err = ERR_NO_NUM;
}
}
else if (kind == SYM_SUB)
{
kind = get_sym();
if (kind != SYM_NUM)
{
err = ERR_NO_NUM;
}
val = -val;
}
else if (kind != SYM_NUM)
{
err = ERR_NO_NUM;
}
}
void F_() // F'->^F|ε
{
if (err != ERR_OK) return ;
SYM_KIND kind = get_sym();
double tmp = val;
if (kind == SYM_POW)
{
F();
val = pow(tmp, val);
}
else if (kind == SYM_ADD || kind == SYM_SUB || kind == SYM_MUL || kind == SYM_DIV
|| kind == SYM_MOD || kind == SYM_END || kind == SYM_RBR)
{
pos--;
}
else if (kind != SYM_ERR)
err = ERR_NO_OPERATOR;
}
void F() // F ->NF'
{
if (err != ERR_OK) return ;
N();
F_();
}
void T_() // T'->*FT'|/FT'|%FT'|ε
{
if (err != ERR_OK) return ;
SYM_KIND kind = get_sym();
double tmp = val;
if (kind == SYM_MUL)
{
F();
val *= tmp;
T_();
}
else if (kind == SYM_DIV)
{
F();
val = tmp / val;
T_();
}
else if (kind == SYM_MOD)
{
F();
val = fmod(tmp, val);
T_();
}
else if (kind == SYM_ADD || kind == SYM_SUB || kind == SYM_RBR || kind == SYM_END)
{
pos--;
}
else if (kind != SYM_ERR)
{
err = ERR_NO_OPERATOR;
}
}
void T() // T ->FT'
{
if (err != ERR_OK) return ;
F();
T_();
}
void E_() // E'->+TE'|-TE'|ε
{
if (err != ERR_OK) return ;
SYM_KIND kind = get_sym();
double tmp = val;
if (kind == SYM_ADD)
{
T();
val = tmp + val;
E_();
}
else if (kind == SYM_SUB)
{
T();
val = tmp - val;
E_();
}
else if (kind == SYM_END || kind == SYM_RBR)
{
pos--;
}
else if (kind != SYM_ERR)
{
err = ERR_NO_OPERATOR;
}
}
void E() // E ->TE'
{
if (err != ERR_OK) return ;
T();
E_();
}
void output_err()
{
if (err == ERR_OK)
{
err = ERR_BR_NOT_MATCH;
pos++;
}
printf("%*s ^", pos, "");
if (err == ERR_BR_NOT_MATCH) printf("括号不比對\n");
else if (err == ERR_NO_NUM) printf("缺少一個數字\n");
else if (err == ERR_NO_OPERATOR) printf("缺少一份運算符\n");
else if (err == ERR_INVALID_CHAR) printf("不合法字元\n");
}
int main()
{
printf(">>");
while (gets(expr) != NULL)
{
pos = ;
err = ERR_OK;
E();
if (err == ERR_END) printf("%g\n", val);
else output_err();
printf(">>");
}
return ;
}
運作結果:
>>3+4^2.2
24.1121
>>2-7/8
1.125
>>(8+0
^括号不比對
>>7%5
2
>>7+9.9+
^缺少一個數字
加個界面……
.net表達式電腦(中綴表達式轉字尾表達式,支援20多個數學函數,支援函數嵌套)
最近在網上查了一下表達工電腦的類庫,發現Java版本的有一個比較成熟的叫W3EVal,好像是一個IBM工程師寫的,.net就很少了(可能是我了解不夠多),但投機取巧的實作思路有很多,比如: (1)将 ...
基于文法分析器GOLD Parser開發的數學表達式電腦
最近發現一款文法分析神器,看完官網(http://goldparser.org/)的介紹後感覺很犀利的樣子,于是就拿來測試了一番,寫了一個數學表達式分析的小程式,支援的數學運算符如下所示:正常運算:+ ...
java面向對象課程設計-數學表達式電腦
項目簡介 設計一個電腦,其能夠: 1)由使用者輸入一個簡單的四則運算表達式,求出其計算結果後顯示. 2)特殊數學函數,如:絕對值.取整.三角函數.倒數.平方根.平方.立方等. 3)對一定範圍内的數字将 ...
Basic Calculator - Stack(表達式電腦)
978. Basic Calculator https://www.lintcode.com/problem/basic-calculator/description public class Sol ...
編譯原理LL1文法分析樹(繪圖過程)算法實作
import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; impo ...
編譯原理LL1文法分析表算法實作
import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg ...
編譯原理LL1文法Follow集算法實作
import hjzgg.first.First; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set ...
編譯原理 LL1文法First集算法實作
import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...
JLS中表達式的所有文法
3.8. Identifiers Identifier: IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral Iden ...
随機推薦
angular路由詳解:
1.$routeProvider ngRoute子產品中的服務 2.otherwise:設定用于路由改變時,與任何其他定義的路由無法比對的時候執行的代碼 3.when:為$route服務定義新的路由 例 ...
hdu1711 KMP
#include #include #define maxn 1000010 int next[maxn],s[maxn],p[maxn] ...
c++ 字元串函數用法舉例
1. substr() 2. replace() 例子:split() 字元串切割: substr 函數原型: , size_t n = npos ) const; 解釋:抽取字元串中從pos(預設為 ...
wireshark: there are no interfaces on which a capture can be done
權限問題,簡單的直接sudo就行. 更安全的做法是: # chmod 4755 /usr/bin/dumpcap dumpcap的所在目錄可用whereis指令檢視.
jquery ajax傳遞數組給php
寫成:var data = {'item[]':item}; $.post(url,data,function(return_data) 寫成item:item會導緻資料缺失. 更多:http://w ...
nginx優化 突破十萬并發(轉)
一.一般來說nginx 配置檔案中對優化比較有作用的為以下幾項: 1. worker_processes 8; nginx 程序數,建議按照cpu 數目來指定,一般為它的倍數 (如,2個四核的cpu計 ...
把centos 網卡接口eth2改成eth0
kvm 虛拟機 複制之後 預設網卡是 eth2了 用 ifconfig -a 指令檢視所有的網絡設定,果然沒有eth0的相關設定,多出來一個eth2.顯示如下:[[email protected] ~]# ifcon ...
AJAX 控件集之TextBoxWatermark(水印文本框)控件
功能: 可以讓TextBox控件初始化的時候擁有水印文字.屬性: TargetControlID :要使用具有水印效果的TextBox控件ID. WatermarkCssCla ...
園 首頁 新随筆 聯系 管理 訂閱 訂閱 RTSP協定轉換RTMP直播協定
RTSP協定轉換RTMP直播協定 RTSP協定也是廣泛使用的直播/點播流媒體協定,最近實作了一個RTSP協定轉換RTMP直播協定的程式,為的是可以接收遠端裝置或伺服器的多路RTSP直播資料,實時轉換為 ...
ThreadLocal終極源碼剖析
目錄一.ThreadLocal1.1 源碼注釋1.2 源碼剖析 雜湊演算法-魔數0x61c88647 set操作 get操作 remove操作1.3 功能測試1.4 應用 ...