2012-03-31 2 views
2

필자는 파이썬에서 컴파일러를 작성하고 있는데 필자는 PLY에서 들여 쓰기를 파싱하는 방법을 알아낼 수 없기 때문에 필기체 렉서를 만들었습니다. 또한, 내 렉서 지금과 같은 몇 가지 yield 문 사용하지만수작업으로 작성한 렉서 (lexer) 용 PLY 인터페이스를 작성하는 방법은 무엇입니까?

def scan(): 
... 
    for i in tokens: 
     if i[0]: yield Token(self.line, i[0] if i[0] in keywords else "ident", i[0]) 
      elif i[1]: 
       if "e" in i[1]: 
        base, exp = i[1].split("e") 
        val = float(base) * 10 ** int(exp) 
       else: val = float(i[1]) 
       yield Token(self.line, "float", val) 
     ... other cases ... 

을, 나는 PLY 파서는 token 방법을 필요로 실현, 그래서 나는 다음과 같다 하나 만들어 :

def token(self): 
    return next(self.scan()) 

실제 검사를 내 테스트에 따르면 scan()을 사용하면 평균 124ms가 걸리지 만 PLY 파서를 사용하면 몇 분 후에 파싱이 시작되지 않습니다. 내 방법에 문제가있는 것으로 보입니다.

또한 이 인터페이스가 될 수 있도록 scan() 메서드의 이름을 바꾸려고했습니다. 파이썬은 다음과 같은 것을 반환합니다.

AttributeError: 'generator' object has no attribute 'type' 

그래서 PLY에는 한 번에 하나의 토큰을 반환하는 메서드가 필요합니다.

메서드를 다시 작성하여 다음 반복을 scan()으로 돌려 주지만 느리지는 않습니까?

def start(...): 
    self.lexer = self.scan() 

def token(...): 
    return next(self.lexer) 

면책 조항 :

+0

그런데 들여 쓰기를 구문 분석하려는 경우에도 대부분의 렉싱에 PLY를 사용할 수 있습니다. 렉서 (lexer)를 통해 모든 공백 개행 문자를 전달하고 토큰 스트림을 후 처리하여 적절한 내제/딕트 토큰을 삽입하십시오. 이 작업을 수행 할 때 구문 분석 단계에 PLY를 사용하지 않았으므로이를 통합 할 필요가 없으므로이 질문에 대답 할 수 없습니다. 그러나 그것은 렉서를 더 쉽게 쓸 수 있도록 해줍니다. – delnan

+0

@delnan _probably_ 작동 할 수 있지만, 또한 알아낼 수없는 것은 들여 쓰기를 처리하기 위해 하나의 규칙에 대해 여러 토큰을 반환하는 방법입니다. 나머지는 이미 코딩 할 수 있습니다. –

답변

0

당신처럼, 어딘가 발전기를 저장해야 내가 PLY에 대해 아무것도 몰라.

+0

작동하지만 프로그램을 확실히 5ms 정도 느리게 진행시킵니다. 그러나 그것은 저를 정말로 괴롭히지 않습니다. 감사! –

관련 문제