2010-02-06 4 views
1

이 코드는 작동합니다대한 파싱 질문

1 - 토큰을 구문 분석하는 사용자 정의 함수를 사용하는 방법 :

from pyparsing import * 

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*" 

zipcode = Regex(zipRE) 
foo = Regex(fooRE) 

query = (zipcode | foo) 



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ] 

for t in tests: 
    try: 
     results = query.parseString(t) 
     print t,"->", results 
    except ParseException, pe: 
     print pe 

나는이 문제에 갇혔어요. 내가 정규식 대신에 일부 사용자 지정 논리를 사용하기를 원한다면 숫자는 우편 번호의 경우 예를 들어, 확인합니다. 아마도

zipcode = Regex(zipRE) 

: 대신

zipcode = MyFunc() 

2 - 나는 문자열의 정보는 다음의 제품에 구문 분석을 결정합니까. "80001"은 "zipcode"로 구문 분석하지만 어떻게 pyparsing을 사용하여 이것을 결정합니까? 그 내용에 대한 문자열을 파싱하는 것이 아니라 단순히 어떤 종류의 쿼리인지 결정하는 것입니다. 당신은 어느 문자열 일치를 알 수 있도록

답변

2

두 번째 질문은 쉽기 때문에 먼저 대답하겠습니다. 다른 표현에 결과 이름을 지정하는 쿼리를 변경합니다

이제
query = (zipcode("zip") | foo("foo")) 

반환 된 결과에 대한 getName()를 호출 할 수 있습니다 :

print t,"->", results, results.getName() 

기부 : 당신이

80517 -> ['80517'] zip 
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1) 
90001-3234 -> ['90001-3234'] zip 
! sfs -> ['! sfs'] foo 

을하려는 경우 결과의 foo 또는 zipness를 사용하여 다른 함수를 호출하려면 foo 및 zipcode 표현식에 구문 분석 조치를 추가하여 구문 분석시이를 수행 할 수 있습니다.

# enclose zipcodes in '*'s, foos in '#'s 
zipcode.setParseAction(lambda t: '*' + t[0] + '*') 
foo.setParseAction(lambda t: '#' + t[0] + '#') 

query = (zipcode("zip") | foo("foo")) 

지금 제공 :

첫 번째 질문에 대한
80517 -> ['*80517*'] zip 
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1) 
90001-3234 -> ['*90001-3234*'] zip 
! sfs -> ['#! sfs#'] foo 

, 나는 정확히 무슨 뜻 기능의 종류를 알 수 없습니다. Pyparsing은 Regex (예 : Word, Keyword, Literal, CaselessLiteral) 이외에 더 많은 파싱 클래스를 제공하며 '+', '|', '^', '~', '@'및 이들을 결합하여 파서를 구성합니다. '*'연산자. 당신이 정규식을 사용하는 미국 사회 보장 번호를 구문 분석,하지만 원한다면 예를 들어, 당신이 사용할 수 있습니다

ssn = Combine(Word(nums,exact=3) + '-' + 
     Word(nums,exact=2) + '-' + Word(nums,exact=4)) 

말씀이 생성자에서 주어진 문자로 구성된 연속 "말"에 대한 일치, 결합 일치하는 토큰을 단일 토큰으로 연결합니다.당신은 '/'s의 사용에 의해 구분 된 같은 숫자의 잠재적 목록에 대해 분석하고 싶었다면

:

delimitedList(ssn, '/') 

또는 전혀 delimters으로, 1 개 3 등의 숫자 사이에이 있다면, 사용 :

ssn * (1,3) 

그리고 어떤 식 결과 이름이 또는 추가 구문 분석하는 동안 구문 분석 결과 또는 기능을 풍부하게하기 위해, 그들에게 부착 작업을 구문 분석 할 수 있습니다. Forward 클래스를 사용하여 중첩 된 괄호, 산술 식 등의 재귀 파서를 빌드 할 수도 있습니다.

필자가 Pyparsing을 작성할 때의 기본 의도는 기본 빌딩 블록에서 파서를 구성하는 것이 파서를 작성하기위한 기본 형식이된다는 것입니다. 가장 최근의 릴리스에서 Regex를 궁극적 인 탈출 밸브로 추가했습니다. 사람들이 파서를 작성할 수 없으면 정규 표현식으로 되돌아 갈 수 있습니다.

또는 다른 포스터에서 알 수 있듯이 pyparsing 소스를 열어 기존 클래스 중 하나를 서브 클래스로 만들거나 구조를 따라 직접 작성할 수 있습니다.

punc = r"[email protected]#$%^&*_-+=|\?/" 
parser = OneOrMore(Word(alphas) | PairOf(punc)) 
print parser.parseString("Does ** this match @@@@ %% the parser?") 

가 제공합니다 :

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser'] 

('?'후행 하나의 누락 참고) 그래서

class PairOf(Token): 
    """Token for matching words composed of a pair 
     of characters in a given set. 
    """ 
    def __init__(self, chars): 
     super(PairOf,self).__init__() 
     self.pair_chars = set(chars) 

    def parseImpl(self, instring, loc, doActions=True): 
     if (loc < len(instring)-1 and 
      instring[loc] in self.pair_chars and 
      instring[loc+1] == instring[loc]): 
      return loc+2, instring[loc:loc+2] 
     else: 
      raise ParseException(instring, loc, "Not at a pair of characters") 

: 여기 쌍 문자와 일치합니다 클래스입니다

+0

이런 사려 깊은 답변에 감사드립니다. 지난 밤에 나는 문자 그대로 꿈꿔 봤다. 나는 내가하려고하는 것을 보여주기위한 모범이 있다고 생각한다. pyparsing 예제 중 하나는 거리 주소를 파싱하는 것입니다. 도시와 주를 구문 분석하기 위해이 코드를 확장하고 싶다면 어떻게 될까요? stateAbbreviation = oneOf ("" "AA AE AK AL ..."(제공 한대로)를 사용하여 상태를 구문 분석 할 수 있습니다. 그러나 다른 코드에서 함수를 호출하여 City를 구문 분석하려면 어쩌면 isStringPlacenmae), 또는 주어진 문자열 placename 경우 말해 줄 수 webservice ... – Art

+0

몇 가지 추가 정보 : 검색 쿼리를 분류하는 구문 분석기를 쓰고 있어요. 쿼리를 주소, 우편 번호, 추적 여부를 확인하려면 바란다. 수식, 수학 식 등 ... – Art

+0

구문 분석 동작은 간단한 식 일치 이상으로 추가 유효성 검사를 추가하는 것이 좋을 수 있습니다. 추가 논리가 실패하면 구문 분석 작업을 수행하여 ParseException을 발생시키고 파서는이를 일치하지 않는 것처럼 처리합니다 원래 표현. – PaulMcG

3

당신은 별도로 우편 번호 및 foo는 사용할 수 있습니다.

zipresults = zipcode.parseString(t) 
fooresults = foo.parseString(t) 
2

은 내가 pyparsing 모듈을 가지고 있지 않지만, Regex는 클래스가 아닌 함수해야합니다.

당신이 할 수있는 일은 그것에서 서브 클래스이며, 동작을 사용자 필요에 따라 다음 대신 서브 클래스를 사용하는 방법을 우선합니다.