본문 바로가기
Computer Science

ply 공식문서 6.8절 번역 (번역기 돌림)

by invrtd.h 2022. 11. 30.

 불특정 다수에게 공유하려고 번역한 건 아닙니다. 프로젝트 하느라 읽어야 되는데 시간이 없어서 빨리 읽어야 하기 때문에... 만약 필요하다면 최대한 원본과 대조해서 읽으시길 바랍니다. 잘못된 번역이 있을 가능성이 높습니다.

 

 

 

 프로덕션에서 사용할 파서를 생성하는 경우 구문 오류를 처리하는 것이 중요합니다. 일반적으로 파서가 단순히 손을 들고 문제의 첫 신호에서 멈추는 것을 원하지 않습니다.프로덕션에서 사용할 파서를 생성하는 경우 구문 오류를 처리하는 것이 중요합니다. 일반적으로 파서가 문제의 징후가 나타나면 손을 들고 멈추기를 원하지 않습니다. 대신 오류를 보고하고 가능한 경우 복구한 다음 구문 분석을 계속하여 입력의 모든 오류가 사용자에게 한 번에 보고되도록 합니다. 이것은 C, C++, Java와 같은 언어용 컴파일러에서 볼 수 있는 표준 동작입니다.

 PLY에서 구문 분석 중에 구문 오류가 발생하면 오류가 즉시 감지됩니다(즉, 파서는 오류의 소스를 초과하는 토큰을 더 이상 읽지 않습니다). 그러나 이 시점에서 파서는 추가 파싱을 시도하고 계속하는 데 사용할 수 있는 복구 모드로 들어갑니다. 일반적으로 LR 파서의 오류 복구는 고대 의식과 블랙 매직과 관련된 섬세한 주제입니다. yacc.py에서 제공하는 복구 메커니즘은 Unix yacc와 유사하므로 자세한 내용은 O'Reilly의 "Lex and Yacc"와 같은 책을 참조하십시오.

 구문 오류가 발생하면 yacc.py은 다음 단계를 수행합니다.

 오류가 처음 발생하면 문제가 되는 토큰을 인수로 사용자 정의 p_error() 함수가 호출됩니다. 그러나 구문 오류가 파일 끝에 도달하여 발생한 경우 p_error()는 없음 인수로 호출됩니다. 그런 다음 파서는 적어도 3개의 토큰을 구문 분석 스택으로 성공적으로 이동할 때까지 p_error()에 대한 이후 호출을 수행하지 않는 "오류 복구" 모드로 들어갑니다.
p_error()에서 복구 작업이 수행되지 않으면 문제가 되는 미리 보기 토큰이 특수 오류 토큰으로 대체됩니다.
문제가 되는 미리 보기 토큰이 이미 오류로 설정된 경우 구문 분석 스택의 맨 위 항목이 삭제됩니다.
전체 구문 분석 스택이 해제된 경우, 파서는 재시작 상태로 들어가고 초기 상태부터 구문 분석을 시작하려고 시도합니다.
문법 규칙이 오류를 토큰으로 허용하면 구문 분석 스택으로 이동됩니다.
구문 분석 스택의 맨 위 항목이 오류인 경우 구문 분석기가 새 기호를 성공적으로 이동하거나 오류와 관련된 규칙을 줄일 수 있을 때까지 미리 보기 토큰이 삭제됩니다.

 

 6.8.1 오류 규칙과 복구 및 재동기화합니다.
 구문 오류를 처리하는 가장 좋은 방법은 오류 토큰을 포함하는 문법 규칙을 작성하는 것입니다. 예를 들어, 언어에 다음과 같은 인쇄 문에 대한 문법 규칙이 있다고 가정합니다.

 

def p_statement_print(p):
    'statement : PRINT expr SEMI'
    ...

 

잘못된 표현식의 가능성을 설명하기 위해 다음과 같은 추가 문법 규칙을 작성할 수 있습니다.

 

 def p_statement_print_error(p):
     'statement : PRINT error SEMI'
     print("Syntax error in print statement. Bad expression")

이 경우 오류 토큰은 발견된 첫 번째 세미콜론까지 표시될 수 있는 토큰 시퀀스와 일치합니다. 세미콜론에 도달하면 규칙이 호출되고 오류 토큰이 사라집니다.

이러한 유형의 복구를 파서 재동기화라고 합니다. 오류 토큰은 잘못된 입력 텍스트에 대한 와일드카드 역할을 하며 오류 직후의 토큰은 동기화 토큰 역할을 합니다.

오류 토큰은 일반적으로 오류 규칙에서 오른쪽의 마지막 토큰으로 표시되지 않습니다. 예를 들어 다음과 같습니다.

 

 def p_statement_print_error(p):
     'statement : PRINT error'
     print("Syntax error in print statement. Bad expression")

 

이는 첫 번째로 발견된 잘못된 토큰으로 인해 규칙이 줄어들기 때문입니다. 따라서 더 많은 잘못된 토큰이 즉시 뒤따를 경우 복구가 어려울 수 있습니다.

6.8.2 패닉 모드 복구.
대체 오류 복구 체계는 파서가 적절한 방식으로 복구할 수 있는 지점까지 토큰이 삭제되는 패닉 모드 복구로 전환하는 것입니다.

패닉 모드 복구는 전적으로 p_error() 함수에서 구현됩니다. 예를 들어, 이 함수는 닫는 '}'에 도달할 때까지 토큰 폐기를 시작합니다. 그런 다음 초기 상태에서 파서를 재시작합니다.

 

def p_error(p):
    print("Whoa. You are seriously hosed.")
    if not p:
        print("End of File!")
        return
 
    # Read ahead looking for a closing '}'
    while True:
        tok = parser.token()             # Get the next token
        if not tok or tok.type == 'RBRACE': 
            break
    parser.restart()

 

 

parser.errok(). 그러면 파서 상태가 재설정되어 오류 복구 모드로 간주되지 않습니다. 이렇게 하면 오류 토큰이 생성되지 않고 내부 오류 카운터가 재설정되어 다음 구문 오류가 p_error()를 다시 호출합니다.
parser.token(). 입력 스트림의 다음 토큰을 반환합니다.
parser.restart(). 그러면 전체 구문 분석 스택이 무시되고 파서가 초기 상태로 재설정됩니다.
파서에 다음 룩어헤드 토큰을 제공하기 위해 p_error()는 토큰을 반환할 수 있습니다. 이 기능은 특수 문자로 동기화하려는 경우 유용할 수 있습니다. 예를 들어 다음과 같습니다.

 

 def p_error(p):
     # Read ahead looking for a terminating ";"
     while True:
         tok = parser.token()             # Get the next token
         if not tok or tok.type == 'SEMI': break
     parser.errok()
 
     # Return SEMI to the parser as the next lookahead token
     return tok

 

위의 오류 처리 함수인 파서는 yacc()에 의해 생성된 파서의 인스턴스입니다. 오류 처리 중에 참조할 수 있도록 이 인스턴스를 코드의 어딘가에 저장해야 합니다.

6.8.3 제품의 오류를 표시합니다.
필요한 경우 프로덕션 규칙이 수동으로 파서를 오류 복구로 강제 전환할 수 있습니다. 이 작업은 다음과 같이 구문 오류 예외를 올림으로써 수행됩니다.

 

 def p_production(p):
     'production : some production ...'
     raise SyntaxError

 

구문 오류 발생 효과는 구문 분석 스택으로 이동된 마지막 기호가 실제로 구문 오류인 경우와 동일합니다. 따라서 이 작업을 수행하면 마지막으로 이동한 기호가 구문 분석 스택에서 분리되고 현재 미리 보기 토큰이 오류 토큰으로 설정됩니다. 그런 다음 오류 토큰을 허용할 수 있는 규칙을 줄이려는 오류 복구 모드로 들어갑니다. 이 시점부터 이어지는 단계는 구문 오류가 감지되고 p_error()가 호출된 경우와 정확히 동일합니다.

수동으로 오류를 설정할 때 한 가지 중요한 점은 이 경우 p_error() 함수가 호출되지 않는다는 것입니다. 오류 메시지를 발행해야 하는 경우 SyntaxError를 발생시키는 프로덕션에서 실행해야 합니다.

참고: PLY의 이 기능은 yacc에서 YYERROR 매크로의 동작을 모방하기 위한 것입니다.

6.8.4 구문 오류가 보고되는 시기입니다.
대부분의 경우 yacc는 입력에서 잘못된 입력 토큰이 감지되는 즉시 오류를 처리합니다. 하지만, yacc가 먼저 하나 이상의 문법 규칙을 줄인 후까지 오류 처리를 지연하도록 선택할 수 있습니다. 이 동작은 예기치 않은 것일 수 있지만 "기본 상태"로 알려진 기본 구문 분석 테이블의 특수 상태와 관련이 있습니다. 기본 상태는 구문 분석 조건으로, 입력에서 다음에 오는 유효한 토큰에 관계없이 동일한 문법 규칙이 축소됩니다. 이러한 상태의 경우, yacc는 다음 입력 토큰을 읽지 않고 문법 규칙을 줄이기로 선택합니다. 다음 토큰이 잘못된 경우, yacc는 결국 그것을 읽을 수 있게 되고 구문 오류를 보고합니다. 문법 규칙 중 일부가 구문 오류 직전에 실행되는 것을 볼 수 있다는 점에서 약간 특이합니다.

일반적으로 기본 상태에서 지연된 오류 보고는 무해합니다(PLY가 이러한 방식으로 작동하기를 원하는 다른 이유도 있음). 그러나 어떤 이유로 이 동작을 해제해야 하는 경우에는 이 옵션을 선택합니다. 다음과 같이 기본 상태 테이블을 지울 수 있습니다.

 

 parser = yacc.yacc()
 parser.defaulted_states = {}

 

문법이 6.11절에 설명된 것처럼 내장된 동작을 사용하는 경우 기본 상태를 비활성화하지 않는 것이 좋습니다.

6.8.5 오류 처리에 대한 일반적인 의견입니다.
일반 유형의 언어의 경우 오류 규칙 및 재동기화 문자를 사용한 오류 복구가 가장 신뢰할 수 있는 기술일 수 있습니다. 복구가 비교적 쉬운 선택된 위치에서 오류를 탐지하고 구문 분석을 계속할 수 있도록 문법을 계측할 수 있기 때문입니다. 패닉 모드 복구는 올바른 재시작 지점을 찾기 위해 입력 텍스트의 많은 부분을 삭제하려는 특정 특수 애플리케이션에서만 유용합니다.

댓글