2015-01-13 17 views
6

Come posso descrivere una grammatica utilizzando regex (o pyparsing è meglio?) Per un languge sceneggiatura presentati qui di seguito (Backus-Naur Form):Convertire BNF grammatica pyparsing

<root> :=  <tree> | <leaves> 
<tree> :=  <group> [* <group>] 
<group> :=  "{" <leaves> "}" | <leaf>; 
<leaves> :=  {<leaf>;} leaf 
<leaf> :=  <name> = <expression>{;} 

<name>   := <string_without_spaces_and_tabs> 
<expression> := <string_without_spaces_and_tabs> 

Esempio dello script:

{ 
stage = 3; 
some.param1 = [10, 20]; 
} * 
{ 
stage = 4; 
param3 = [100,150,200,250,300] 
} * 
endparam = [0, 1] 

io uso python re.compile e voglio dividere tutto in gruppi, qualcosa di simile:

[ [ 'stage',  '3'], 
    [ 'some.param1', '[10, 20]'] ], 

[ ['stage', '4'], 
    ['param3', '[100,150,200,250,300]'] ], 

[ ['endparam', '[0, 1]'] ] 

Aggiornamento: Ho scoperto che il pyparsing è una soluzione molto migliore invece di regex.

+0

si può solo ridurre la grammatica sostituendo tutti i nodi non terminali per ottenere una regex. Tuttavia, a cosa serve questo? Il risultato restituirebbe semplicemente un flusso di token per la stringa di input, ma non preserverebbe alcuna struttura, necessaria per dare un senso semantico al codice. –

+1

Qui c'è un convertitore ABNF-to-regex: http://www.akr.org/abnf/ –

+0

Vedi anche questa domanda relativa allo Stack Overflow: http://stackoverflow.com/questions/8898049/how-to-convert -a-regular-grammar-to-regular-expression –

risposta

4

Pyparsing consente di semplificare alcuni di questi tipi di costrutti

leaves :: {leaf} leaf 

a poco

OneOrMore(leaf) 

Così una forma di tuo BNF in pyparsing avrà un aspetto simile:

from pyparsing import * 

LBRACE,RBRACE,EQ,SEMI = map(Suppress, "{}=;") 
name = Word(printables, excludeChars="{}=;") 
expr = Word(printables, excludeChars="{}=;") | quotedString 

leaf = Group(name + EQ + expr + SEMI) 
group = Group(LBRACE + ZeroOrMore(leaf) + RBRACE) | leaf 
tree = OneOrMore(group) 

Ho aggiunto quotedString come expr alternativo, nel caso in cui volessi avere qualcosa che ha fatto include uno dei caratteri esclusi. E l'aggiunta del gruppo attorno a foglia e gruppo manterrà la struttura di rinforzo.

Purtroppo, il campione non del tutto conforme a questa BNF:

  1. spazi in [10, 20] e [0, 1] renderli invalidi exprs

  2. alcune foglie non hanno terminare ; s

  3. solitario * caratteri - ???

Questo campione non analizzare correttamente con il parser di cui sopra:

sample = """ 
{ 
stage = 3; 
some.param1 = [10,20]; 
} 
{ 
stage = 4; 
param3 = [100,150,200,250,300]; 
} 
endparam = [0,1]; 
""" 

parsed = tree.parseString(sample)  
parsed.pprint() 

Dare:

[[['stage', '3'], ['some.param1', '[10,20]']], 
[['stage', '4'], ['param3', '[100,150,200,250,300]']], 
['endparam', '[0,1]']]