word :: group of alphabetic characters salutation :: word comma :: "," greetee :: word endPunctuation :: "!" greeting :: salutation comma greetee endPunctuation이것은 BNF형태이다. 기호를 표현하는 데는 아주 많은 방법이 있다.
from pyparsing import Word, Literal, alphas salutation = Word( alphas + """ ) comma = Literal(",") greetee = Word( alphas ) endPunctuation = Literal("!") greeting = salutation + comma + greetee + endPunctuationPypasring의 여러 기능은 개발자가 텍스트 파싱 기능을 빠르게 개발하도록 돕는다.
from pyparsing import Word, Literal, alphas salutation = Word( alphas + """ ) comma = Literal(",") greetee = Word( alphas ) endPunctuation = Literal("!") greeting = salutation + comma + greetee + endPunctuation tests = ("Hello, World!", "Hey, Jude!", "Hi, Mom!", "G"day, Mate!", "Yo, Adrian!", "Howdy, Pardner!", "Whattup, Dude!" ) for t in tests: print t, "->", greeting.parseString(t) =========================== Hello, World! -> ["Hello", ",", "World", "!"] Hey, Jude! -> ["Hey", ",", "Jude", "!"] Hi, Mom! -> ["Hi", ",", "Mom", "!"] G"day, Mate! -> ["G"day", ",", "Mate", "!"] Yo, Adrian! -> ["Yo", ",", "Adrian", "!"] Howdy, Pardner! -> ["Howdy", ",", "Pardner", "!"] Whattup, Dude! -> ["Whattup", ",", "Dude", "!"]Pyparsing은 조합자(Combinator)이다
number :: "0".. "9"* phoneNumber :: [ "(" number ")" ] number "-" number이것은 전화번화 내에서 괄호와 대시(-)를 찾기 때문에 이 구두점 표시를 위해 간단한 토큰을 정의 할 수 있다.
dash = Literal( "-" ) lparen = Literal( "(" ) rparen = Literal( ")" )전화번호 내에서 숫자를 정의하기 위해서 다양한 길이의 문자열을 처리할 필요가 있다. 이를 위해서는 Word토큰을 사용하라
digits = "0123456789" number = Word( digits )숫자 토큰은 숫자로 나열되는 문자로 구성된 연속된 열과 일치할 것이다. 즉 이것은 숫자로 구성된 단어이다.(알파벳으로 구성되는 전형적인 단어와는 반대로) 이제 전화번호에 대한 각각의 문자열을 얻었으므로 이제 And 클래스를 사용하여 이것들을 문자열로 만들 수 있다.
phoneNumber = And( [ lparen, number, rparen, number, dash, number ] )이것은 읽기에 자연스럽지 않다. 다행히도 pyparsing모듈은 좀더 쉽게 각 파서 요소를 조합하기 위한 연산자 메서드를 정의한다. 좀더 읽기 쉬운 정의는 And를 위해 +를 사용한다.
phoneNumber = lparen + number + rparen + number + dash + number좀더 쉽게 하기 위해 +연산자는 묵시적으로 문자 그대로 변환되는 파서 요소와 문자를 묶는다. 이것이 읽기에 더 쉽다.
phoneNumber = "(" + number + ")" + number + "-" + number최종적으로 전화번호의 첫 부분에 지역 번호가 선택적임을 나타내기 위해 pyparsing의 Optional클래스를 사용한다.
phoneNumber = Optional( "(" + number + ")" ) + number + "-" + number문법 사용하기
Hello, World! -> ["Hello", ",", "World", "!"]비록 이것이 토큰 문자열의 간단한 리스트로 보이긴 하지만 pyparsing은 ParseResults 오브젝트를 사용하여 데이터를 리턴한다. 위 예제에서 결과 값들은 파이썬의 리스트 데이터처럼 보인다. 사실 리스트 데이터처럼 단지 결과에 순서를 붙일 수도 있다.
print results[0] print results[-2]는 다음과 같이 나타난다.
Hello WorldparseResult를 이용하여 각 문장에 이름을 정의할 수도 있다. 이것은 파싱된 텍스트와 비트열을 반복적으로 검사하는 것을 더욱 쉽게 해 준다. 이것은 특히 문법이 선택적인 부분을 포함하고 있을 때 유용하다. 이 문법은 리턴된 토큰 리스트의 길이와 오프셋을 변경할 수 있다.
salute = Word( alphas+""" ).setResultsName("salute") greetee = Word( alphas ).setResultsName("greetee")마치 리턴된 결과의 속성인 것처럼 대응되는 토큰을 참조할 수 있다.
print hello, "->", results print results.salute print results.greetee위의 내용은 다음과 같이 나타난다.
G"day, Mate! -> ["G"day", ",", "Mate", "!"] G"day Mate위 결과는 당신이 작성한 파싱 프로그램의 가독성과 유지 보수성을 향상 시키는데 커다란 도움을 준다.
phoneNumberList = OneOrMore( phoneNumber ) data = phoneNumberList.parseString( inputString )이것은 pyparsing의 ParseResult 오브젝트 형태로 데이터를 리턴할 것이고 이 오브젝트는 입력 전화번호의 모든 리스트를 가지고 있다.
phoneNumberList = delimitedList( phoneNumber )이것은 전과 같은 전화번호 리스트를 리턴한다. dellimiteList는 모든 표현식과 문자열을 지원한다. 콤마 구분자가 가장 일반적이어서 기본으로 사용된다.
for data,dataStart,dataEnd in phoneNumber.scanString( mailingListText ): . . # 전화번호 토큰으로 뭔가를 한다, # data변수에 리턴된다 . .마지막으로 같은 메일링 리스트를 가지고는 있지만 잠재저인 전화 판매원으로부터 전화번호를 숨기고자 하는 경우 모든 전화번호를 (000)000-0000문자열로 변환하는 파서 동작을 추가하여 문자열을 변환 할 수 있다.
phoneNumber.setParseAction( replaceWith("(000)000-0000") ) sanitizedList = phoneNumber.transformString( originalMailingListText )적절한 입력에 대한 동작이 정의 되지 않은 경우
pyparsing.ParseException: Expected "!" (at char 12), (line:1, col:13)이를 바탕으로 입력문자열을 수정하거나 문장에 대해 좀더 관대한 문법을 작성할 수 있다. 위의 경우에 올바른 문장 종결자로 물음표를 지원하면 된다.
이전 글 : DHCP 구현과 이해
다음 글 : 파이썬으로 재귀하향 파서 만들기(2)
최신 콘텐츠