用高階的語言寫 parser 總是大家心中的痛,面對一個簡單的 String 「1 + 2 * 5 - log(4 / tan(3/4))」,若是自己硬幹一個 parser 實在痛苦到不行。原本我已經打定主意來學 lex & yacc,準備自己來實作了,好在終於讓我找到 java 的 library XD。不過話說回來,似乎我自己蒐尋的時候沒下對關鍵字啊... 這套 library 叫 Java Math Expression Parser,簡稱 JEP,官網點此進入。看一下它的 feature,嗯...,該有的都有了。不過卡到一個問題,這個玩意實在有夠貴!試用版只能支援 50 個 expression,似乎夠了?但是只能用在教育方面,而實際要買的話,這玩意要 600 美金。XD 以後我也來考慮寫些 library來賣錢好了...。好在估狗大神萬能,在 3.x 版本之前的 2.4.x 版本是 GPL 授權的,馬上在 sourceforge 找到!這裡可以下載。這下子終於可以安心的用 JEP 來開發程式囉。 話說它的使用方法真是相當簡單,一開始先宣告一個 JEP 物件,然後呼叫此物件的 addStandardFunction() 這個 method,就可以呼叫 parseExpression() 開始 parse,然後再用 getValue() 取得值。簡單來說會長這樣:(記得 import org.nfunk.jep.*) JEP parser = new JEP(); String expr = "1 + 2 + 3"; parser.addStandardFunction(); parser.parseExpression(expr); // handling errors while parsing double value = parser.getValue(); // handling errors during evaluation 值得注意的是,在 JEP 中,預設的 data type 會是 double,若想採用其他的 data type 可以自己呼叫 API 來轉換。而error 的部分可以呼叫 parser.hasError(),若是 true 就表示有 error。 2.4 版本的 JEP 比起商業化後的 3.x 版本就缺了一些功能,比如說我想要以 2 為底的 log,也就是一般常見的 lg,在 JEP 3.x 有支援,2.4 就沒有了,因此我想要自己加一個 function 進去,這要怎麼做呢?首先我們用一個 class,並 extend PostfixMathCommand,接下來就可以開始了。 import org.nfunk.jep.*; import org.nfunk.jep.function.*; import java.util.Stack; public class Lg extends PostfixMathCommand { public Lg() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack); Object param = inStack.pop(); if (param instanceof Double) { double r = ((Double)param).doubleValue(); r = Math.log(r) / Math.log(2); inStack.push(new Double(r)); } else { throw new ParseException("invalid parameter type"); } } } 而在原本的地方要用,就用 addFunction() 這個 method,例如 parser.addFunction("lg", new Lg()),如此就可以搞定了。
文章標籤
全站熱搜
創作者介紹
創作者 zwai 的頭像
zwai

zwai 小窩

zwai 發表在 痞客邦 留言(0) 人氣(3,073)