2013-08-04 2 views
2

나는 여전히 나 자신을 훑어보기에 초보자라고 생각한다. 나는 2 개의 빠른 문법을 함께 던졌지 만 어느 것도 성공하려고 노력하지 않는다. 나는 정말로 간단하게 보이는 문법을 생각해 내려고 노력하고있다. 그러나 그것은 (적어도 나를 위해) 그렇게 사소하지는 않다. 언어에는 하나의 기본 정의가 있습니다. 키워드와 본문 텍스트로 분류됩니다. 몸은 여러 줄에 걸쳐있을 수 있습니다. 키워드는 처음 20 자 정도의 줄 시작 부분에 있지만 ';' (따옴표 제외). 그래서 저는 몇 가지 문법으로 테스트 할 수있는 간단한 데모 프로그램을 만들었습니다. 그러나 나는 그들을 사용하려고 할 때, 그들은 항상 첫 번째 키워드를 얻는다.문법을 사용하여 텍스트에서 하나 이상의 키워드를 읽을 수 있음

예제로 소스 코드를 첨부하고 발생하는 출력을 첨부했습니다. 이 코드는 테스트 코드 일 뿐이므로 습관적으로 문서 작업을 수행했습니다. 아래의 예에서 두 키워드는 NOW입니다. 마지막으로 이상적으로는 세미콜론을 키워드에 포함시키지 않을 것입니다.

내가이 작업을하기 위해해야 ​​할 아이디어가 있습니까?

from pyparsing import * 

def testString(text,grammar): 
    """ 
    @summary: perform a test of a grammar 
    2type text: text 
    @param text: text buffer for input (a message to be parsed) 
    @type grammar: MatchFirst or equivalent pyparsing construct 
    @param grammar: some grammar defined somewhere else 
    @type pgm: text 
    @param pgm: typically name of the program, which invoked this function. 
    @status: 20130802 CODED 
    """ 
    print 'Input Text is %s' % text 
    print 'Grammar is %s' % grammar 
    tokens = grammar.parseString(text) 
    print 'After parse string: %s' % tokens 
    tokens.dump() 
    tokens.keys() 

    return tokens 


def getText(msgIndex): 
    """ 
    @summary: make a text string suitable for parsing 
    @returns: returns a text buffer 
    @type msgIndex: int 
    @param msgIndex: a number corresponding to a text buffer to retrieve 
    @status: 20130802 CODED 
    """ 

    msg = [ """NOW; is the time for a few good ones to come to the aid 
of new things to come for it is almost time for 
a tornado to strike upon a small hill 
when least expected. 
lastly; another day progresses and 
then we find that which we seek 
and finally we will 
find our happiness perhaps its closer than 1 or 2 years or not so 
    """, 
     '', 
     ] 

    return msg[msgIndex] 

def getGrammar(grammarIndex): 
    """ 
    @summary: make a grammar given an index 
    @type: grammarIndex: int 
    @param grammarIndex: a number corresponding to the grammar to be retrieved 
    @Note: a good run will return 2 keys: NOW: and lastly: and each key will have an associated body. The body is all 
    words and text up to the next keyword or eof which ever is first. 
    """ 
    kw = Combine(Word(alphas + nums) + Literal(';'))('KEY') 
    kw.setDebug(True) 
    body1 = delimitedList(OneOrMore(Word(alphas + nums)) +~kw)('Body') 
    body1.setDebug(True) 
    g1 = OneOrMore(Group(kw + body1)) 

    # ok start defining a new grammar (borrow kw from grammar). 

    body2 = SkipTo(~kw, include=False)('BODY') 
    body2.setDebug(True) 

    g2 = OneOrMore(Group(kw+body2)) 
    grammar = [g1, 
      g2, 
      ] 
    return grammar[grammarIndex] 


if __name__ == '__main__': 
    # list indices [ text, grammar ] 
    tests = {1: [0,0], 
     2: [0,1], 
     } 
    check = tests.keys() 
    check.sort() 
    for testno in check: 
    print 'STARTING Test %d' % testno 
    text = getText(tests[testno][0]) 
    grammar = getGrammar(tests[testno][1]) 
    tokens = testString(text, grammar) 
    print 'Tokens found %s' % tokens 
    print 'ENDING Test %d' % testno 

출력은 다음과 같습니다 : 여기에 전체 테스트 및 대안-선택 인프라를 (파이썬 2.7을 사용하고 2.0.1 대한 파싱) 내가 TDD와 괜찮아

STARTING Test 1 
    Input Text is NOW; is the time for a few good ones to come to the aid 
    of new things to come for it is almost time for 
    a tornado to strike upon a small hill 
    when least expected. 
    lastly; another day progresses and 
    then we find that which we seek 
    and finally we will 
    find our happiness perhaps its closer than 1 or 2 years or not so 

    Grammar is {Group:({Combine:({W:(abcd...) ";"}) {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}} [, {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}}]...})}... 
    Match Combine:({W:(abcd...) ";"}) at loc 0(1,1) 
    Matched Combine:({W:(abcd...) ";"}) -> ['NOW;'] 
    Match {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}} [, {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}}]... at loc 4(1,5) 
    Match Combine:({W:(abcd...) ";"}) at loc 161(4,20) 
    Exception raised:Expected W:(abcd...) (at char 161), (line:4, col:20) 
    Matched {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}} [, {{W:(abcd...)}... ~{Combine:({W:(abcd...) ";"})}}]... -> ['is', 'the', 'time', 'for', 'a', 'few', 'good', 'ones', 'to', 'come', 'to', 'the', 'aid', 'of', 'new', 'things', 'to', 'come', 'for', 'it', 'is', 'almost', 'time', 'for', 'a', 'tornado', 'to', 'strike', 'upon', 'a', 'small', 'hill', 'when', 'least', 'expected'] 
    Match Combine:({W:(abcd...) ";"}) at loc 161(4,20) 
    Exception raised:Expected W:(abcd...) (at char 161), (line:4, col:20) 
    After parse string: [['NOW;', 'is', 'the', 'time', 'for', 'a', 'few', 'good', 'ones', 'to', 'come', 'to', 'the', 'aid', 'of', 'new', 'things', 'to', 'come', 'for', 'it', 'is', 'almost', 'time', 'for', 'a', 'tornado', 'to', 'strike', 'upon', 'a', 'small', 'hill', 'when', 'least', 'expected']] 
    Tokens found [['NOW;', 'is', 'the', 'time', 'for', 'a', 'few', 'good', 'ones', 'to', 'come', 'to', 'the', 'aid', 'of', 'new', 'things', 'to', 'come', 'for', 'it', 'is', 'almost', 'time', 'for', 'a', 'tornado', 'to', 'strike', 'upon', 'a', 'small', 'hill', 'when', 'least', 'expected']] 
    ENDING Test 1 
    STARTING Test 2 
    Input Text is NOW; is the time for a few good ones to come to the aid 
    of new things to come for it is almost time for 
    a tornado to strike upon a small hill 
    when least expected. 
    lastly; another day progresses and 
    then we find that which we seek 
    and finally we will 
    find our happiness perhaps its closer than 1 or 2 years or not so 

    Grammar is {Group:({Combine:({W:(abcd...) ";"}) SkipTo:(~{Combine:({W:(abcd...) ";"})})})}... 
    Match Combine:({W:(abcd...) ";"}) at loc 0(1,1) 
    Matched Combine:({W:(abcd...) ";"}) -> ['NOW;'] 
    Match SkipTo:(~{Combine:({W:(abcd...) ";"})}) at loc 4(1,5) 
    Match Combine:({W:(abcd...) ";"}) at loc 4(1,5) 
    Exception raised:Expected ";" (at char 7), (line:1, col:8) 
    Matched SkipTo:(~{Combine:({W:(abcd...) ";"})}) -> [''] 
    Match Combine:({W:(abcd...) ";"}) at loc 5(1,6) 
    Exception raised:Expected ";" (at char 7), (line:1, col:8) 
    After parse string: [['NOW;', '']] 
    Tokens found [['NOW;', '']] 
    ENDING Test 2 

    Process finished with exit code 0 

답변

2

하지만 정말에 도착 문법이 어디에 있고 무엇이 진행되고 있는지를 보는 방법. 나는 모든 여분의 기계를 벗겨 경우에, 나는 문법은 그냥 참조 :

kw = Combine(Word(alphas + nums) + Literal(';'))('KEY') 
body1 = delimitedList(OneOrMore(Word(alphas + nums)) +~kw)('Body') 
g1 = OneOrMore(Group(kw + body1)) 

내가 볼 수있는 첫 번째 문제는 body1의 당신의 정의입니다 :

body1 = delimitedList(OneOrMore(Word(alphas + nums)) +~kw)('Body') 

당신은 음 (가) 오른쪽 궤도에 Lookahead,하지만 pyparsing에서 작동하기 위해서는 끝 부분이 아닌 표현의 시작 부분에 넣어야합니다. "나는 다른 유효한 단어를 일치하기 전에, 내가 먼저 키워드임을 배제 할 것이다."이라고 생각 :

body1 = delimitedList(OneOrMore(~kw + Word(alphas + nums)))('Body') 

을 (왜 그런데, 이것을 delimitedList입니다 delimitedList하는 것은 일반적으로 사실 목록을 위해 예약되어 있습니다 프로그램 함수에 쉼표로 분리 된 인수와 같은 구분 기호가 붙은.이 모든 것은 쉼표 목록을 사용하여보다 직접적으로 처리해야하는 쉼표를 수락합니다.

여기 내 테스트 버전 귀하의 코드 :

from pyparsing import * 

kw = Combine(Word(alphas + nums) + Literal(';'))('KEY') 
body1 = OneOrMore(~kw + Word(alphas + nums))('Body') 
g1 = OneOrMore(Group(kw + body1)) 

msg = [ """NOW; is the time for a few good ones to come to the aid 
of new things to come for it is almost time for 
a tornado to strike upon a small hill 
when least expected. 
lastly; another day progresses and 
then we find that which we seek 
and finally we will 
find our happiness perhaps its closer than 1 or 2 years or not so 
    """, 
      '', 
      ][0] 

result = g1.parseString(msg) 
# we expect multiple groups, each containing "KEY" and "Body" names, 
# so iterate over groups, and dump the contents of each 
for res in result: 
    print res.dump() 

나는 여전히 당신과 같은 결과를 얻었지만 첫 번째 키워드 만 일치합니다.

result,start,end = next(g1.scanString(msg)) 
print len(msg),end 

나에게 제공합니다 :

320 161 

를 따라서 분리가 일어나는 곳을보고, 나는 일치하는 토큰뿐만 아니라 일치하는 토큰의 시작과 끝뿐만 아니라 반환, scanString를 사용 그래서 우리는 총 길이가 320 인 문자열에 위치 (161)에서 끝나는 것을 볼, 그래서 나는 한 번 더 인쇄 문을 추가 할 것입니다 :

print msg[end:end+10] 

를 내가 얻을 :

. 
lastly; 

본문 텍스트의 마침표는 범인입니다. 나는이 메시지에서 것을 제거하고 다시 parseString을하려고하면, 지금 얻을 :

PUNC = oneOf(". , ? ! : & $") 

및 body1에 추가 : 당신이 문장을 처리하려면

['NOW;', 'is', 'the', 'time', 'for', 'a', 'few', 'good', 'ones', 'to', 'come', 'to', 'the', 'aid', 'of', 'new', 'things', 'to', 'come', 'for', 'it', 'is', 'almost', 'time', 'for', 'a', 'tornado', 'to', 'strike', 'upon', 'a', 'small', 'hill', 'when', 'least', 'expected'] 
- Body: ['is', 'the', 'time', 'for', 'a', 'few', 'good', 'ones', 'to', 'come', 'to', 'the', 'aid', 'of', 'new', 'things', 'to', 'come', 'for', 'it', 'is', 'almost', 'time', 'for', 'a', 'tornado', 'to', 'strike', 'upon', 'a', 'small', 'hill', 'when', 'least', 'expected'] 
- KEY: NOW; 
['lastly;', 'another', 'day', 'progresses', 'and', 'then', 'we', 'find', 'that', 'which', 'we', 'seek', 'and', 'finally', 'we', 'will', 'find', 'our', 'happiness', 'perhaps', 'its', 'closer', 'than', '1', 'or', '2', 'years', 'or', 'not', 'so'] 
- Body: ['another', 'day', 'progresses', 'and', 'then', 'we', 'find', 'that', 'which', 'we', 'seek', 'and', 'finally', 'we', 'will', 'find', 'our', 'happiness', 'perhaps', 'its', 'closer', 'than', '1', 'or', '2', 'years', 'or', 'not', 'so'] 
- KEY: lastly; 

, 당신이 같은 것을 추가 제안

body1 = OneOrMore(~kw + (Word(alphas + nums) | PUNC))('Body') 
+0

의견을 보내 주셔서 감사합니다. 잘만되면 곧 나는이 느낌을 갖기 시작할 것이다. – Div

+0

또한 scanString 팁에 감사드립니다. 나는 그것을 사용할 계획이다. – Div