문제

나는 음영 엔진을위한 컴파일러를 작성하고 있으며, 진술 부분에 도달 할 때까지 모든 것이 잘 작동했습니다.

나는 an을 사용했다 초록 구문 트리 모든 작업을 수행하기 위해 클래스로 정의됩니다 (타이프 체크 및 중간 코드 생성을 단순화하기 위해) .. 조상 클래스가 있습니다. ASTNode 그리고 모든 내림차순 클래스와 같은 ASTFloat, ASTExpression, ASTIdentifier 등등..

~ 안에 .y 파일 공통적으로 AST를 구축 할 수 있습니다.

nexp:
T_LPAR nexp T_RPAR { $$ = $2; }
| nexp OP_PLUS nexp { $$ = new ASTBExpression('+', (ASTExpression*)$1, (ASTExpression*)$3); }
| nexp OP_MINUS nexp { $$ = new ASTBExpression('-', (ASTExpression*)$1, (ASTExpression*)$3); }
| nexp OP_TIMES nexp { $$ = new ASTBExpression('*', (ASTExpression*)$1, (ASTExpression*)$3); }

그리고 그것은 꽤 잘 작동하지만 나는 범위에 대한 진술을 생성하려고 노력했습니다 (예 : 만약에 진술) 이런 식으로 : 나는 수업을 사용했습니다. ASTStatements 목록이 있습니다 ASTNode* 각 진술이 발생하면 파서에 의해 채워져야합니다.

따라서 접근 방식은 다음과 비슷합니다.

statements:
statement { if ($$ == null) $$ = new ASTStatements(); ((ASTStatements*)$$)->addStatement($1); } statements { $$->generateASM(); }
;

문제는 항목이 명세서 블록 당 한 번만 초기화되어야한다는 것입니다. 그러나 어떻게 해야하는지 모르겠습니다. 사용 if ($$ == null) 내가 시도한 해킹이지만 작동하지 않기 때문에 yylval 그 시점까지 무엇이든 포함 할 수 있습니다.

들소를 사용하여 이런 종류의 상황을 처리하는 일반/가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책 3

나는 진술 목록이 아니라 퇴보 된 나무를 생성 하여이 문제를 해결했습니다. 따라서 관련된 클래스 객체는 다음과 같습니다.

ASTStatements
{
    ASTStatements *m_next;
    ASTStatement *m_statement;

    ....

    public:
        ASTStatements(ASTStatement *statement) // used for last one
        ASTStatements(ASTStatement *stat, ASTStatements *next) // used with a next one
}

규칙을 사용합니다 .y 다음 방법으로 :

statements: /* empty */ { $$ = null; }
| statements statement { if ($1 == null) $$ = new ASTStatements($2); else $$ = new ASTStatements($2, (ASTStatements*)$1); }

그리고 실제로 이것은 좌측 수반이며, 스택을 어수선하지 않고 가능한 빨리 진술을 줄일 수 있습니다. 나는 내 언어와 관련된 다른 종류의 "기호 목록"에 대해 같은 접근법을 따랐다 ..

다른 팁

다음과 같은 증강 문법을 사용해보십시오.

statements: statement { $$ = new ASTStatements();
                       ((ASTStatements*)$$)->addStatement($1); }      
 | statements statement { ((ASTStatements*)$$)->addStatement($2); }

이것이 도움이 될지 확실하지 않습니다.

YACC의 좌익 규칙을 선호 해야하는 여러 가지 이유가 있습니다. 한 가지는 입력에서 가능한 한 빨리 줄일 수 있습니다.

어쨌든 그렇게하면 다음과 같은 패턴을 사용할 수 있습니다.

statements:                { $$ = new ... }
    | statements statement { /* now $1 and $2 do just what you want */ }
    ;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top