%{
#include <stdio.h>
#include <stdlib.h>

extern int yylex(void);
void yyerror(const char *msg) {
        fprintf(stderr, "Rai RAI! %s\n", msg);
        exit(1);
}
int labelstack[1024];
int labelstackp = 0;
int nextlabel = 0; 
 
%}

%token raiE raiQ rairai RAI RAIEE RAIRAI raiDDD raiD

%%

program : {
        puts("bits 32");
        puts("section .text");
        puts("global _start");
        puts("_start:");
        puts("\tmov ecx, memory");
        }
        statementlist
        {
                puts("\tcall exit");
                
                puts("exit:");
                puts("\tmov eax, 1");
                puts("\tint 0x80");
                
                puts("getchar:");
                puts("\tmov eax, 3");
                puts("\tmov ebx, 0");
                puts("\tmov edx, 0");
                puts("\tint 0x80");
                puts("\tret");
                
                puts("putchar:");
                puts("\tmov eax, 4");
                puts("\tmov ebx, 1");
                puts("\tmov edx, 1");
                puts("\tint 0x80");
                puts("\tret");
                
                puts("section .data");
                puts("memory: times 4096 db 0");
                puts("END");
        }
        ;

statementlist : statement
              | statement statementlist
              ;

statement : raiE { puts("\tinc ecx"); }
          | raiQ { puts("\tdec ecx"); }
          | rairai { puts("\tinc byte [ecx]"); }
          | RAI { puts("\tdec byte [ecx]"); }
          | RAIEE { printf("label%d_in:\n", nextlabel);
                    puts("\tcmp byte [ecx], 0");
                    printf("\tjz label%d_out\n", nextlabel);
                    labelstack[labelstackp] = nextlabel;
                    labelstackp++;
                    nextlabel++; }
            statementlist
            RAIRAI {
                  labelstackp--;
                  printf("\tjmp label%d_in\n", labelstack[labelstackp]);
                  printf("label%d_out:\n", labelstack[labelstackp]); }
          | raiDDD { puts("\tcall getchar"); }
          | raiD { puts("\tcall putchar"); }
          ;

%%

int main() {
        yyparse();
        return 0;
}
