2016-11-19 7 views
0

PyParsing에서 다중 행인데 정말 간단하게 구문 분석하려고하지만 작동하지 않는 이유를 고민하고 있습니다. 구문 분석하려는 문자열은 다음과 같습니다.다중 행 PyParsing 예

string = '''START 
    1 10; % Name1 
    2 20; % Name2 
END''' 

나는 시작과 끝 토큰 사이의 모든 라인이 int 또는 float 유형이 될 수있는 하나 이상의 양/음 숫자를 포함하는 것이라는 점을 알고있다. 또한 사용자가 % 기호 뒤에 추가 메타 데이터를 추가 할 수도 있습니다.

그래서 저는 수레와 이름에 대한 기본 문법을 정의하는 것으로 시작합니다.

Float = Word(nums + '.' + '-') 
Name = Word(alphanums) 

나는 선이 % Name에 의해 선택적으로 세미콜론 다음에 하나 이상의 Float를 포함 할 수 있음을 알고있다.

Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd()) 

많은 줄이 예상되므로 다음과 같이 줄의 문법을 정의 할 수 있습니다. 가능한 검색 할 this answer 폴에 의해 제안

Lines = OneOrMore(Group(Line)) 

나는 Group를 사용합니다.

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END')) 

grammar.parseString(string) 

그러나이 쉽게 복사 및 붙여 넣기에 대해 다음

ParseException: Expected end of line (at char 62), (line:3, col:19) 

전체 코드 아래라는 오류가 발생합니다.

string = '''START 
    1 10; % Name1 
    2 20; % Name2 
END''' 

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group 

Float = Word(nums + '.' + '-') 
Name = Word(alphanums) 
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd()) 
Lines = OneOrMore(Group(Line)) 

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END')) 
grammar.parseString(string) 

편집 : 나는 어느 아무 소용이 다음과 같은 노력했습니다

.

string = '''START 
    1 10; % Name1 
    2 20; % Name2 
END''' 

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group 

Float = Word(nums + '.' + '-') 
Name = Word(alphanums) 
NL = Suppress(LineEnd()) 
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(~NL + 
                  Suppress(Literal('%')) 
                  + OneOrMore(Name)('name') + NL) | NL 
Lines = OneOrMore(Group(Line)) 

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END')) 
grammar.parseString(string) 

내가

Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(restOfLine) 

그러나이 구조화 된 방식으로 세미콜론 후 일부를 반환하지 않습니다 restOfLine를 사용하는 경우 제대로 작동 않는 유일한 것은 내가 그것을 구문 분석해야 따로 따로. 그것이 권장 접근법입니까?

+0

"Name.setDebug()"및 "Float.setDebug()"를 추가하고 해당 출력이 도움이되는지 확인하십시오. – PaulMcG

+0

그 출력은'OneOrMore (Name)'이 줄 끝보다 더 멀리 나아가고 있다고 제안하는 것 같습니다. OneOrMore (Name)이 줄 끝에서 멈추는 지 확인하는 좋은 방법은 무엇입니까? 나는 OneOrMore (Name) + NL을 시도했으나 그 중 하나도 작동하지 않았고 이유를 이해할 수 없었습니다. – kdheepak

+0

우선 "2"는 유효한 이름입니까? 둘째, 문장의 마지막 부분이 중요합니까? 그렇다면 ParserElement.setDefaultWhitespaceChars (https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#setDefaultWhitespaceChars의 문서 인라인 예제 참조)를 사용하여 무시할 수있는 공백 세트에서 삭제해야합니다. 마지막으로, Float과 Name의 정의를 강화하고자 할 수 있습니다. 지금 가지고있는 것처럼, "...", "---"및 "1.1"과 같은 문자열이 Float와 일치합니다.1 "이고 Name은"12345 "와"221B "가 일치합니다 – PaulMcG

답변

1

기본 공백 문자에서 새 줄을 제거하는 것이이 문제를 해결하는 데 필요한 것입니다. 바울이 자신의 의견에서 제안한 바대로, 부유물과 이름을 더 엄격하게 분석 할 수 있도록 다른 개선안을 만들 수 있습니다.

string = '''START 
    1 10; % Name1 
    2 20; % Name2 
END''' 

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group, ParserElement 

ParserElement.setDefaultWhitespaceChars(" \t") 

Float = Word(nums + '.' + '-') 
Name = Word(alphanums) 
NL = Suppress(LineEnd()) 
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(~NL + 
                  Suppress(Literal('%')) 
                  + OneOrMore(Name)('name') + NL) | NL 
Lines = OneOrMore(Group(Line)) 

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END')) 
grammar.parseString(string)