2015-01-13 18 views
6

Làm thế nào tôi có thể mô tả một ngữ pháp sử dụng regex (hoặc pyparsing là tốt hơn?) Cho một languge kịch bản trình bày dưới đây (Backus-Naur Form):Chuyển đổi BNF ngữ pháp để 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> 

Ví dụ về kịch bản:

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

tôi sử dụng python re.compile và muốn chia mọi thứ thành từng nhóm, một cái gì đó như thế này:

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

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

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

Cập nhật: Tôi đã phát hiện ra rằng pyparsing là giải pháp tốt hơn nhiều thay vì regex.

+0

Bạn chỉ có thể làm giảm ngữ pháp bằng cách thay thế tất cả các nút không bị đầu cuối để có được một regex. Tuy nhiên, điều này sẽ làm gì tốt? Kết quả sẽ đơn giản trả về một luồng mã thông báo cho chuỗi đầu vào của bạn, nhưng sẽ không giữ lại bất kỳ cấu trúc nào, được yêu cầu để tạo ra ý nghĩa ngữ nghĩa của mã. –

+1

Có bộ chuyển đổi ABNF-sang-regex tại đây: http://www.akr.org/abnf/ –

+0

Cũng xem câu hỏi Stack Overflow có liên quan này: http://stackoverflow.com/questions/8898049/how-to-convert -a-thường-ngữ pháp-to-regular-expression –

Trả lời

4

Pyparsing cho phép bạn đơn giản hóa một số các loại cấu trúc

leaves :: {leaf} leaf 

chỉ

OneOrMore(leaf) 

Vì vậy, một hình thức BNF của bạn trong pyparsing sẽ giống như thế:

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) 

Tôi đã thêm quotedString làm expr thay thế, trong trường hợp bạn muốn có một cái gì đó mà đã làm bao gồm một trong các ký tự bị loại trừ. Và thêm nhóm xung quanh lá và nhóm sẽ duy trì cấu trúc giằng.

Thật không may, mẫu của bạn không hoàn toàn phù hợp với BNF này:

  1. khoảng trống trong [10, 20][0, 1] làm cho họ exprs không hợp lệ

  2. một số lá không có chấm dứt ; s

  3. lone * ký tự - ???

mẫu này phân tích thành công với phân tích cú pháp trên:

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

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

Giving:

[[['stage', '3'], ['some.param1', '[10,20]']], 
[['stage', '4'], ['param3', '[100,150,200,250,300]']], 
['endparam', '[0,1]']] 
Các vấn đề liên quan