2012-10-17 4 views
3

parseString이 올바른 결과를 제공하는 경우 scanString이 작동하도록하는 데 문제가 있습니다.parseString이 작동합니까? scanString이 실패합니까?

이 순서는 작동합니다

alpha_rev = pyp.Word(pyp.alphas, max=2) 
num_rev = pyp.Word('123456789', max=2) 
space = pyp.White(ws=" ").suppress() 

revisionExpr = (
    pyp.StringStart().leaveWhitespace() + 
    space + 
    pyp.Combine(alpha_rev + 
    pyp.Optional(num_rev)("rev")) 
    ) 

rev_string = ' K  WI, This is the title' 

for match_str, start, end in (
    revisionExpr.scanString(rev_string, maxMatches=1)): 
    print match_str 

['K'] 

는 때때로 "계"또는 "목사"가 개정 전에; 실패 :

revisionExpr = (
    pyp.StringStart().leaveWhitespace() + 
    space + 
    pyp.Combine(alpha_rev + 
    pyp.Optional(num_rev)("rev")) 
    | 
    pyp.CaselessLiteral("Rev") + pyp.Optional('.') + 
    pyp.Combine(alpha_rev + 
    pyp.Optional(num_rev)("rev")) 
    ) 

for match_str, start, end in (
    revisionExpr.scanString(rev_string, maxMatches=1)): 
    print match_str 

print match_str 
NameError: name 'match_str' is not defined 

왜 "|" 경기가 실패하게 만들었습니까? 첫 번째 예와 같은 형태로, 그것이 내가 "추가하면 작동 | 내가 (" "는 후) 마지막 예제의 두 번째 부분을 추출 할 경우

revisionTokens = revisionExpr.parseString(rev_string) 

이 제 1 및 제 2 예에서 모두 작동합니다 회전." rev_string의 "K"앞에 표시됩니다. 불행하게도 첫 번째 표현식의 공백 문자는 수정 문자열을 고유하게 식별하는 데 필요합니다. 그렇지 않으면이 예에서 "WI"가 일치합니다.

나중에 처리하는 데 도움이되는 일치 항목의 시작 및 끝 위치를 반환하기 때문에 parseString 대신 scanString을 사용하려고합니다.

답변

2

문제는 "or"연산자 ("|")가 요소의 왼쪽과 오른쪽에있는 요소 만보고 있다는 것입니다. 문법 요소를 올바르게 그룹화하지 않았습니다. 여기에 귀하의 문법 나눠 좀 더 :

left_expr = pyp.Combine(alpha_rev + pyp.Optional(num_rev)("rev") 
right_expr = pyp.CaselessLiteral("Rev") 

joined_expr = left_expr | right_expr 

final_expr = (pyp.StringStart().leaveWhitespace() + 
    space + 
    joined_expr + 
    pyp.Optional('.') + 
    pyp.Combine(alpha_rev + 
     pyp.Optional(num_rev)("rev")) 
    ) 

당신이 볼 수 있듯이, 이것은 당신이 원하는 것을 확실히 아니다 - 또 다른 다음, 텍스트 "계"또는 실제 버전 중 하나를 찾을 것 개정. 식의 고정 된 버전은 다음과 같습니다 : 그러나

revisionExpr = (
    pyp.StringStart().leaveWhitespace() + 
    space + 
    (
     pyp.Combine(alpha_rev + 
      pyp.Optional(num_rev)("rev") 
     ) 
     | 
     (
      pyp.CaselessLiteral("Rev") + 
      pyp.Optional('.') + 
      pyp.Combine(alpha_rev + 
       pyp.Optional(num_rev)("rev")) 
     ) 
    ) 
) 

, 당신은보다 간결 조금 문법을 만들 수 있습니다 :이 버전에서

revisionExpr = (
    pyp.StringStart().leaveWhitespace() + 
    space + 
    pyp.Suppress(
     pyp.Optional(
      pyp.CaselessLiteral("Rev") + 
      pyp.Optional('.') 
     ) 
    ) + 
    pyp.Combine(
     alpha_rev + 
     pyp.Optional(num_rev)("rev") 
    ) 
) 

, 당신은 단지 "목사"표시 텍스트를 선택적으로 구문 분석 옵션을 구문 분석에 제공하는 대신 예상되는 위치에 배치하거나 "Rev." + 개정. 이렇게하면 "|" 연산자.

PyParsing이 연산자 오버로딩을 사용하여 더 멋진 구문을 제공한다는 것을 잊지 마십시오. 구문이 혼란을 일으키는 경우 (예 : pyp.Or (a)와 같은 긴 형식의 메서드 호출을 사용하는 것이 더 나을 수 있습니다) , b) ".