2013-02-26 97 views
1

我正在使用ParseKit解析度量單位。爲了做到這一點,我必須提供一個語法。我嘗試了谷歌搜索,但沒有讓我走得很遠。雖然這是一個有趣的練習,但我希望確保自己做對了。 ParseKit期待一個BNF語法是這樣的:BNF用於計量單位的語法

@start = number units; 
units = unit+ | unit+/unit+; 
unit = prefix baseUnit | baseUnit; 
prefix = '' | 'milli' | 'micro' | 'pico'; 
baseUnit = 'm' | 'meter' | 'g' | 'gram' 

我正在尋找支持像輸入:

25 m² 
25 m^-3 
25 m**-5/kg**-2 
25 m/s squared 
25 mm² per second 
25 m/s 
5 kg meters per second squared 
3 m-kg/s^2 
3 m kilograms 
+0

您是否在尋找幫助改善您發佈的語法,以便它完全支持您期望的輸入? – rmaddy 2013-02-26 01:24:18

+0

@rmaddy很高興有一個官方/非官方語法的參考,但改進是值得歡迎的。 – 2013-02-26 01:37:55

+0

什麼是「我」?什麼是'kge'? – 2013-02-26 03:41:37

回答

1

開發的ParseKit這裏。

我沒有仔細查看您的示例輸入以確定您的語法是否語義正確。

但是,我看到兩個重要的語法問題與您的現有語法。


首先,該行包含左遞歸(並與未加引號/語法錯誤):

units = unit+ | unit+/unit+; // Incorrect. Will not work. 

您必須更改此行以卸下左遞歸是這樣的:

units = unit ('/' unit)*; 

參見my prior answer for more information on eliminating Left Recursion in your ParseKit grammars


其次,我相信此行試圖通過使用''允許一個「空」的比賽:

prefix = '' | 'milli' | 'micro' | 'pico'; // Incorrect. Will not work. 

,是不是在ParseKit語法支持的語法。此功能完全支持,但語法是Empty,如:

prefix = Empty | 'milli' | 'micro' | 'pico'; 

希望有所幫助。

+0

優秀。這清除了一些東西。最後,我可以解析「皮克」而不是「皮克」。我沒有看到有關如何解析子字符串的文檔中的任何內容。 – 2013-03-02 22:01:44

+0

我想我需要自定義PKTokenizer,但我不知道從哪裏開始。 – 2013-03-02 22:13:53

+0

你可以從這裏標記我的答案開始正確(或至少upvoting),然後問一個關於分詞:)的新問題。我及時回答標有「ParseKit」的所有問題。 – 2013-03-02 22:15:33

1

This grammar我在unidata.ucar.edu發現看起來很正式,雖然不方便的和不包含前綴或單位。

單位,規格: 的一個什麼 按住Shift鍵規格

Shift-Spec: one of 
     Product-Spec 
     Product-Spec SHIFT REAL 
     Product-Spec SHIFT INT 
     Product-Spec SHIFT Timestamp 

Product-Spec: one of 
     Power-Spec 
     Product-Spec Power-Spec 
     Product-Spec MULTIPLY Power-Spec 
     Product-Spec DIVIDE Power-Spec 

Power-Spec: one of 
     Basic-Spec 
     Basic-Spec INT 
     Basic-Spec EXPONENT 
     Basic-Spec RAISE INT 

Basic-Spec: one of 
     ID 
     "(" Shift-Spec ")" 
     LOGREF Product_Spec ")" 
     Number 

Number: one of 
     INT 
     REAL 

Timestamp: one of 
     DATE 
     DATE CLOCK 
     DATE CLOCK CLOCK 
     DATE CLOCK INT 
     DATE CLOCK ID 
     TIMESTAMP 
     TIMESTAMP INT 
     TIMESTAMP ID 

SHIFT: 
     <space>* <shift_op> <space>* 

<shift_op>: one of 
     "@" 
     "after" 
     "from" 
     "since" 
     "ref" 

REAL: 
     the usual floating-point format 

INT: 
     the usual integer format 

MULTIPLY: one of 
     "-" 
     "." 
     "*" 
     <space>+ 
     <centered middot> 

DIVIDE: 
     <space>* <divide_op> <space>* 

<divide_op>: one of 
     per 
     PER 
     "/" 

EXPONENT: 
     ISO-8859-9 or UTF-8 encoded exponent characters 

RAISE: one of 
     "^" 
     "**" 

ID: one of 
     <id> 
     "%" 
     "'" 
     "\"" 
     degree sign 
     greek mu character 

<id>: 
     <alpha> <alphanum>* 

<alpha>: 
     [A-Za-z_] 
     ISO-8859-1 alphabetic characters 
     non-breaking space 

<alphanum>: one of 
     <alpha> 
     <digit> 

<digit>: 
     [0-9] 

LOGREF: 
     <log> <space>* <logref> 

<log>: one of 
     "log" 
     "lg" 
     "ln" 
     "lb" 

<logref>: 
     "(" <space>* <re> ":"? <space>* 

DATE: 
     <year> "-" <month> ("-" <day>)? 

<year>: 
     [+-]?[0-9]{1,4} 

<month>: 
     "0"?[1-9]|1[0-2] 

<day>: 
     "0"?[1-9]|[1-2][0-9]|"30"|"31" 

CLOCK: 
     <hour> ":" <minute> (":" <second>)? 

TIMSTAMP: 
     <year> (<month> <day>?)? "T" <hour> (<minute> <second>?)? 

<hour>: 
     [+-]?[0-1]?[0-9]|2[0-3] 

<minute>: 
     [0-5]?[0-9] 

<second>: 
     (<minute>|60) (\.[0-9]*)?