天天看點

LL1文法JAVA文法輸入_表達式電腦(LL1文法)

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集

LL1文法JAVA文法輸入_表達式電腦(LL1文法)

LL(1)分析表

LL1文法JAVA文法輸入_表達式電腦(LL1文法)

(應該沒錯吧……表示昨天剛考完試……)

(嗯。。我承認我抄。。咳咳。。借鑒了這份代碼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+

^缺少一個數字

加個界面……

LL1文法JAVA文法輸入_表達式電腦(LL1文法)

&period;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文法分析樹&lpar;繪圖過程&rpar;算法實作

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&plus;&plus; 字元串函數用法舉例

1. substr() 2. replace() 例子:split() 字元串切割: substr 函數原型: , size_t n = npos ) const; 解釋:抽取字元串中從pos(預設為 ...

wireshark&colon; 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優化 突破十萬并發&lpar;轉&rpar;

一.一般來說nginx 配置檔案中對優化比較有作用的為以下幾項: 1. worker_processes 8; nginx 程序數,建議按照cpu 數目來指定,一般為它的倍數 (如,2個四核的cpu計 ...

把centos 網卡接口eth2改成eth0

kvm 虛拟機 複制之後 預設網卡是 eth2了 用 ifconfig -a 指令檢視所有的網絡設定,果然沒有eth0的相關設定,多出來一個eth2.顯示如下:[[email protected] ~]# ifcon ...

AJAX 控件集之TextBoxWatermark&lpar;水印文本框&rpar;控件

功能:       可以讓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 應用 ...