2012-11-30 2 views
0

간단한 while 문을 C 언어 (ANSI 89)에서 & t의 어셈블리로 변환하는 프로그램의 yacc 소스 파일을 작성하려고합니다. 다음은 yacc 파일의 중심 부분 인 내 문법입니다.yacc을 사용하여 while 문을 c에서 assembly로 변환

%% 
while_statement  : 'w' 'h' 'i' 'l' 'e' '(' control_statement ')' '{' block '}' 
{printing of the assembly code;} 
control_statement : expression '>' expression { $$ = strcat(write exp jg back,) ;} 
     | expression '<' expression { $$ = strcat(write exp jl back,) ;} 
     | expression '==' expression { $$ = strcat(write exp je back,) ;} 
     | expression '<=' expression { $$ = strcat(write exp jle back,) ;} 
     | expression '>=' expression { $$ = strcat(write exp jge back,) ;} 
     | expression '!=' expression { $$ = strcat(write exp jne back,) ;} 
     | expression { $$ = $1;} 

block   : expression ';' 
     | block expression ';' 

expression  :  expression '+' expression { $$ = $1 + $3;} 
     |  expression '-' expression { $$ = $1 - $3;} 
     |  expression '*' expression { $$ = $1 * $3;} 
     |  expression '/' expression { if($3 == 0) 
           yyerror("divide by zero"); 
           else 
           $$ = $1/$3;} 
     |  '-' expression   { $$ = -$2;} 
     |  '(' expression ')'  { $$ = $2;} 
     | string '=' expression  { create new variable called string with expression value } 
     |  number    { $$ = $1;} 

string   : letter {$$ = $1;} 
     | string letter {strcat($$, ??;} 

letter   : A {strcat($$, 'A');} 
     ......... 

number   : digit  { $$ = $$ + $1;} 
     |  number digit { $$ = ($1 * 10) + $2;} 

digit : '0' {$$ = 0;} 
| '1' {$$ = 1;} 
| '2' {$$ = 2;} 
| '3' {$$ = 3;} 
| '4' {$$ = 4;} 
| '5' {$$ = 5;} 
| '6' {$$ = 6;} 
| '7' {$$ = 7;} 
| '8' {$$ = 8;} 
| '9' {$$ = 9;}  
%% 

제 질문은 : 마지막 종류의 문자열 값을 연결하는 데 사용해야하는 종류의 기능입니까? 또는 어떤 종류의 데이터 형식, 구조체, 공용체 등을 사용해야합니까? 미리 답변 해 주셔서 감사합니다.

답변

1

음, while 루프를 들어, 당신이 원하는 것은 같은 : 그래서

start-label: 
code to evaluate condition 
conditional branch if-false to end-label 
code for the body of the loop 
unconditional branch to start-label 
end-label: 

당신의 의사 코드에서 그 같이 보일 것입니다 :

while_statement: WHILE '(' condition ')' '{' block '}' 
    { $$ = concatenate("start-label:", $3, "jfalse end-label", $6, "jmp start-label", "end-label:"); } 

concatenate이 다른 문자열의 무리 중 문자열을 구축하는 데 사용하는 무엇이다.

문자열을 함께 연결하여 어셈블리 코드를 작성한다고 가정 할 때 (이는 의사 코드에서 수행하려는 것처럼 보입니다.) 또한, 하나 이상의 문자를 허용하려는 경우 고정 문자열을 사용하는 대신 고유 한 레이블을 만들어 각각에 사용할 필요가 있습니다.

+0

+1하지만 조건 테스트를 끝까지 넣고 분기 테스트로 시작하는 것이 좋습니다. 그렇게하면 반복 당 하나의 점프 만 있습니다. 또한 do/while에 대한 코드와 동일하게되며 초기 점프가 추가됩니다. – EJP

1

흠.
당신의 문법을 이해하는 한, 당신은 yacc를 사용하기 시작했습니다. 그것 때문에 나쁘지는 않습니다. 그래서 몇 가지 힌트를 드리겠습니다.
a. 컴파일 타임에 평가하기 때문에 현재 모든 표현식은 상수 일 수 있다는 것을 알고 있습니다. plus case-case {$$ = $1 + $3}으로 작성하면 yacc가 실행되는 동안이 표현식이 평가됩니다. 런타임에이 값을 계산하려면 {emit ("add", allocReg(), $1, $3);}과 같은 올바른 어셈블러 명령을 내 보내야합니다.이 함수는 emit이 처음에는 $1$3의 레지스터 이름 만 가질 수 있습니다.
b. 당신이 (있는 일부 가사를 할 필요) 레지스터에 숫자를로드 할 수-경우에 작업을 변경할 것 그런 경우, 즉, 수에 대한 조치는

{reg=allocReg(); 
emit ("mov", reg, $$); 
} 

(물론 것 할당 된 레지스터가 더 이상 사용되지 않을 때, 예를 들어 추가 작업에서 summands로 사용 된 후에 할당 된 모든 레지스터를 해제해야합니다.
c. 조건을 뛰어 넘기 전에 비교 지시를 내 보내야합니다. 비교할 수 있습니다. cmp $1, $3
d. yacc을 사용할 때, 데이터를 $$에 할당하여 '위쪽으로'전송하고, 다른 규칙에 의해 생성 된 $ 1 ... $ n을 사용합니다. 이 데이터는 규칙에 따라 다른 유형을 가질 수 있습니다. 그래서 그것을 위해 노동 조합을 사용하여 당신의 생각은 (모든 문법 파일 어딘가에 간다) 그렇게 할 수있는 방법이와

typedef union { 
    int    number; 
    char    singleChar; 
    VarName   *var; 
    ... 
} dataVariant; 
#undef YYSTYPE 
#define YYSTYPE dataVariant 

당신이 $$처럼 문법 뭔가 쓸 수 수 = $ 1이다.. 번호. 또한 더 편안 yacc를 내부에 노동 조합이-구성 %, 당신이 그것에 대해 뭔가를 읽을 수 있습니다 : Lex and YACC primer

관련 문제