BNF语法用于计量单位

时间:2013-02-26 01:20:41

标签: objective-c grammar units-of-measurement bnf parsekit

我正在使用ParseKit来解析度量单位。为了做到这一点,我必须提供语法。我试过谷歌搜索,但这并没有让我走得太远。虽然这是一个有趣的练习我想确保我做对了。 ParseKit期待像这样的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

2 个答案:

答案 0 :(得分:1)

This grammar我发现unidata.ucar.edu看起来很官方但不含前缀或单位。

单位规格:其中之一              没有              换档规格

 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]*)?

答案 1 :(得分:1)

ParseKit的开发人员。

我没有仔细查看您的示例输入,以确定您的语法是否在语义上正确。

然而,我看到现有语法的两个重要语法问题。


首先,这一行包含Left Recursion(以及带有不带引号的/的语法错误):

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

您必须更改此行以将Left Recursion移除为以下内容:

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';

希望有所帮助。