2013-02-26 1 views
1

J'utilise ParseKit pour analyser les unités de mesure. Pour ce faire, je dois fournir une grammaire. J'ai essayé de googler mais cela ne m'a pas loin. Bien que ce soit un exercice amusant, je veux m'assurer de bien faire les choses. Parsekit attend une grammaire BNF comme ceci:BNF Grammaire pour les unités de mesure

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

Je cherche à soutenir l'entrée comme:

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

Vous cherchez de l'aide pour améliorer votre grammaire postée afin qu'elle soutienne entièrement votre entrée désirée? – rmaddy

+0

@rmaddy bien ce serait bien d'avoir une référence à une grammaire officielle/non officielle mais les améliorations sont les bienvenues. –

+0

Qu'est-ce que 'me''? Qu'est-ce que 'kge'? –

Répondre

1

Développeur de ParseKit ici.

Je n'ai pas examiné de près votre exemple d'entrée pour déterminer si votre grammaire est sémantiquement correcte.

Toutefois, voir deux problèmes syntaxiques importants avec votre grammaire existante.


D'abord, cette ligne contient Gauche Recursion (et aussi une erreur de syntaxe avec le unquoted /):

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

Vous devez modifier cette ligne pour enlever la gauche Recursion à quelque chose comme ceci:

units = unit ('/' unit)*; 

Voir my prior answer for more information on eliminating Left Recursion in your ParseKit grammars.


En second lieu, je crois que cette ligne tente de permettre une correspondance « vide » en utilisant '':

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

non pris en charge la syntaxe dans les grammaires Parsekit. Cette fonctionnalité est entièrement pris en charge mais la syntaxe est Empty, comme:

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

espoir qui aide.

+0

Excellent. Cela efface un certain nombre de choses. Enfin, je peux analyser quelque chose comme "pico grammes" mais pas "picogrammes". Je n'ai rien vu dans les docs sur la façon d'analyser les sous-chaînes. –

+0

Je suppose que j'ai besoin de personnaliser PKTokenizer mais je ne sais pas par où commencer. –

+0

Vous pouvez commencer par marquer ma réponse ici correcte (ou au moins upvoting) et ensuite poser une nouvelle question à propos de tokenizing :). Je réponds à toutes les questions étiquetées 'ParseKit' ici en temps opportun. –

1

This grammar j'ai trouvé sur unidata.ucar.edu semble assez officielle si unwieldily et ne contenir les préfixes ou les unités.

Unité-Spec: l'un des rien 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]*)? 
Questions connexes