2013-02-26 3 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

+0

@rmaddy хорошо было бы хорошо иметь ссылку на официальную/неофициальную грамматику, но улучшения приветствуются. –

+0

Что такое 'me'? Что такое 'kge'? –

ответ

1

Разработчик ParseKit здесь.

Я не смотрел внимательно на ваш пример ввода, чтобы определить, является ли ваша грамматика семантически правильной.

Однако I do см. Две существенные синтаксические проблемы с существующей грамматикой.


Во-первых, эта строка содержит леворекурсивные (а также ошибка синтаксиса с некотируемого /):

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

Отлично. Это проясняет ситуацию. Наконец, я могу разобрать что-то вроде «пико граммов», но не «пикограмм». Я ничего не видел в документах о том, как разбирать подстроки. –

+0

Я думаю, мне нужно настроить PKTokenizer, но я не уверен, с чего начать. –

+0

Вы можете начать, отметив мой ответ здесь правильным (или, по крайней мере, повышением), а затем задав новый вопрос о токенизации :). Я отвечаю на все вопросы, помеченные «ParseKit» здесь своевременно. –

1

This grammar я нашел на unidata.ucar.edu выглядит довольно официальный, хотя unwieldily и не содержат префиксы или единицы.

Unit-Spec: один из ничего Shift-Spec

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