1

우리는 Al Aho의 컴파일러 클래스 용 컴파일러를 작성하고 있으며 우리 AST 생성을위한 다음 코드를 고려하고 있습니다. 다음은 몇 가지 배경입니다. 우리는 name-id 매핑의 스택으로 범위 지정 규칙을 구현하기를 원합니다. 우리가 들어가서 선언을위한 노드를 생성하기 전에 일련의 매핑을 스택에 푸시하고자합니다.다음 스 니펫은 AST 생성에 어떻게 작용합니까?

compound_statement : {pushScope();} statement_list {popScope();} 

그럼, 여기 내 질문입니다. 이게 어떻게 작동합니까? 이 코드는 언제 실행됩니까? 이 프로덕션이 파서에 의해 축소되면 실행됩니까? 어떤 부분이 언제 생깁니 까? 알아 내야 할 근무 시간에 가야합니까?

답변

1

귀하의 질문은 AST 노드를 구축하는 것에 대해 이야기하지만, 설명의 본문에는 기호 테이블에 관한 내용이 담겨 있습니다. 이 아이디어는 동일하지 않습니다! AST는 프로그램의 구조를 나타냅니다. 기호 표는 표시되는 이름에 대한 추론을 나타냅니다.

기호 테이블에 따라 블록을 "입력"할 때 현재 범위를 밀고 나가는 것처럼 개념을 적용하면 개념적으로 블록 당 새로운 범위를 달성하므로 개념적으로 옳습니다.

문법 규칙의 어느 시점에서든 의미 론적 조치를 취할 수 있는지 확신 할 수 없기 때문에 YACC가 말한 것을 할 수 있다고 생각하지 않습니다. 규칙 전체에 작업을 첨부 할 수 있다고 생각합니다.이 작업은 규칙이 인식 ("축소")되었을 때만 실행됩니다. 그래서 이것을 정말로 원한다면, 의미 론적 행동을 삽입 할 수있는 기회를 창출하기 위해 문법을 구부리기를 원할 것입니다. 당신은 (나는 생각하지 않는다이 실제로 유효한 YACC 문법 당신의 스타일 다음) 규칙을 다시 작성하여이 작업을 수행 할 수 있습니다 :

compound_statement : block_start statement_list block_end ; 
    block_start = '{' pushScope() ; 
    block_end = '}' popScope(); 

내가 시작을 차단하고 대칭 적으로 종료 작업을 추가,하지만 당신은 할 수 있습니다 좀 더 음, 인색 (미소) : 원래 규칙에 하위 규칙을 추가하여 블록을 입력 한 후

compound_statement : block_start statement_list '}' popScope() ; 
    block_start = '{' pushScope() ; 

가 진짜 비밀은 여기 감소/세만 틱 액션 실행 기회를 작성했다. 나는 종종 빈 규칙을 사용하여이 일을했습니다

compound_statement : '{' compound_statement_sub_rule block_start statement_list '}' popScope() ; 
    compound_statement_sub_rule = pushScope() ; 

는이 작업을 수행하는 방법의 종류를 표시하는 데, 난 당신이 모든이 작업을 수행 할 수 있다고 생각하지 않습니다. 당신이하는 일은 파싱 과정에서 의미를 뒤죽박죽으로 다루는 것입니다. 이 경로를 따라 가면 식별자 작성/조회를위한 복잡한 동작으로 문법의 나머지 부분을 꾸미는 자신을 발견하게됩니다. 일반적으로 의미 론적 작업을 사용하여 구문 트리를 작성한 다음 구문 분석이 완료된 후 구문 트리를 이동하여 기호 테이블 구성/식별자 조회를 구현하는 것이 일반적입니다.

나는 그들이 바보 같다고 생각하든, 생각하지 않든, 많은 시간 동안 질문을하고 싶습니다. 그것은 멋지게 갚을 것이다.

+0

-1 이렇게 수동으로 빈 규칙을 만드는 것은 무의미한 것입니다. yacc이 허용하면 모든 힘든 일을 처리 할 것입니다. 또한, 구문 지시 번역 (Aho의 저서)의 전체 요점은 구문 분석 트리를 작성하고 별도의 패스로 통과하는 오버 헤드를 피하기위한 것입니다. 따라서 이것이 Aho 클래스에 실제로 해당된다면, 그렇게하지 않을 수도 있습니다. –

+0

@Chris Dodd : 그러면 yacc이 의미 론적 동작을 사용하여 더미 규칙을 삽입 할 것이라고 말하고 있습니까? 승인. 필자가 보았던 대부분의 LALR 파서 생성기는 그렇게 희귀하지 않기 때문에 여분의 툴링은 불필요 해 보인다. "구문 지시 번역"에 관해서는 당신이 맞습니다. 만약 그들이하는 일이라면 모든 것을 함께 짜 넣어야 할 것입니다. 합리적인 사람은 OP의 문제 문장을 해석 할 것입니다. "우리는 AST 생성을 위해 다음 코드를 고려하고 있습니다."는 구문 지시 변환을 수행하지 않았 음을 나타냅니다. "아호의 책"은 전적으로 구문 지향 번역에 관한 것이 아닙니다. –

0

yacc에서 규칙의 '중간'에 액션을 적용하면 실제로 숨겨진 비 터미널이 숨겨진 비 터미널을 줄이면 액션에 대한 새로운 비 터미널이 생성되고 규칙이 실행됩니다. 그래서 규칙 : 그들이 옳은 일을 참조 yacc에 제대로 행동에 $ N 참조를 수정하는 것을 추가로

compound_statement : hidden_rule statement_list {popScope();} ; 
hidden_rule : {pushScope();} ; 

:

compound_statement : {pushScope();} statement_list {popScope();} ; 

는 것과 동일합니다됩니다.

hidden_rule이 감소 할 때 popScope이 실행되는 동안 모든 문이 감소 후 그래서 pushScope는합니다 (statement_list의 모든 문이 감소되기 전입니다) 실행됩니다, 그래서 사실이 뜻을 정확히 당신이 원하는 것을 할.

+0

nit : 규칙을 작성하는 방식으로, statement_list가 있는지 여부에 관계없이 pushScope가 발생합니다. 확실히 OP가 원하는 것은 아닙니다. 그는 진술서 목록의 시작 (나는 그가 "블록"을 의미했던 것 같음)이 처리되었고 다른 축소가 없음을 확인해야합니다. 내 대답에는 필요한 '{'... '}'토큰이 포함되어 있지만 Yacc 구문은 약간 꺼져있을 수 있습니다. –

관련 문제