2011-02-16 4 views
6

제 렉스 파서로 ply를 사용하고 있습니다. 내 사양은 다음과 같습니다Ply Lex 구문 분석 문제

"while n <= 0 then h = 1" 

그것은 출력 다음 제공합니다 : 나는 다음과 같은 문자열을 구문 분석 할 때

t_WHILE = r'while' 
t_THEN = r'then' 
t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*' 
t_NUMBER = r'\d+' 
t_LESSEQUAL = r'<=' 
t_ASSIGN = r'=' 
t_ignore = r' \t' 

그런 다음 토큰을 인식하지 못하는

LexToken(ID,'while',1,0) 
LexToken(ID,'n',1,6) 
LexToken(LESSEQUAL,'<=',1,8) 
LexToken(NUMBER,'0',1,11) 
LexToken(ID,'hen',1,14)  ------> PROBLEM! 
LexToken(ID,'h',1,18) 
LexToken(ASSIGN,'=',1,20) 
LexToken(NUMBER,'1',1,22) 

, 대신 식별자로 "암탉"을 사용합니다.

아이디어가 있으십니까?

+0

좋아, 문제를 발견했다. – Karan

+0

사실, 나는 t_ignore = r "\ t"때문에 "t"라는 글자를 무시하고있는 것을 발견했다. (왜 그런지 물어 보지 마라!). 그래서 그것을 제거하고 이제 "다음"을 토큰으로 사용하기 시작합니다. – Karan

+1

@Karan :'r '\ t''은 * raw * 문자열입니다. 내 생각 엔'\ t'가 이스케이프 될 수 없었고 처음'r' =>'t_ignore = '\ t''을 제거했다면 효과가있었습니다. – ereOn

답변

7

이것이 작동하지 않는 이유는 우선 순위가 우선 순위가 높은 토큰과 일치하는 것과 관련이 있기 때문에 가장 긴 토큰 정규식이 먼저 테스트됩니다.

이 문제를 방지하는 가장 쉬운 방법은 동일한 유형의 식별자와 예약어를 일치시키고 해당 일치를 기반으로 적절한 토큰 유형을 선택하는 것입니다. 다음 코드는 가장 긴 정규 표현식에 따라 단순 문자열로 선언 된 토큰의 우선 순위를 ply documentation

import ply.lex 

tokens = [ 'ID', 'NUMBER', 'LESSEQUAL', 'ASSIGN' ] 
reserved = { 
    'while' : 'WHILE', 
    'then' : 'THEN' 
} 
tokens += reserved.values() 

t_ignore = ' \t' 
t_NUMBER = '\d+' 
t_LESSEQUAL = '\<\=' 
t_ASSIGN = '\=' 

def t_ID(t): 
    r'[a-zA-Z_][a-zA-Z0-9_]*' 
    if t.value in reserved: 
     t.type = reserved[ t.value ] 
    return t 

def t_error(t): 
    print 'Illegal character' 
    t.lexer.skip(1) 

lexer = ply.lex.lex() 
lexer.input("while n <= 0 then h = 1") 
while True: 
    tok = lexer.token() 
    if not tok: 
     break 
    print tok 
4

PLY의 예와 유사하지만, 함수로 선언 된 토큰은 그들의 순서는 우선 순위가 있습니다. 그들이 나타나는

  1. 기능에 의해 정의 된 모든 토큰이 같은 순서로 추가됩니다 순서에 따라

    마스터 정규 표현식을 구축, 규칙이 에 추가됩니다 워드 프로세서

    렉서 파일에.

  2. 문자열로 정의 된 토큰은 정규식 길이가 감소하는 순서로 정렬하여 추가됩니다 (긴 표현식은 먼저 이 추가됩니다).

    def t_WHILE(t): r'while'; return t 
    def t_THEN(t): r'then'; return t 
    t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*' 
    t_NUMBER = r'\d+' 
    t_LESSEQUAL = r'<=' 
    t_ASSIGN = r'=' 
    t_ignore = ' \t' 
    

    이 방법 WHILE 다음 첫 번째 규칙이 될 것입니다 :

그래서, 대안 솔루션과 같이, 대신 문자열로, 당신은 함수로 우선 순위를 원하는 토큰을 지정하는 단순히 것 추가하면 예상 한 동작을 얻게됩니다.

부수적으로, 당신은 r' \t' (원시 문자열)을 t_ignore에 사용 했으므로 파이썬은 \을 백 슬래시로 처리하고있었습니다. 위의 예에서와 같이 대신 간단한 문자열이어야합니다.