Skip to content

Instantly share code, notes, and snippets.

@LTe
Created June 10, 2010 08:12
Show Gist options
  • Save LTe/432695 to your computer and use it in GitHub Desktop.
Save LTe/432695 to your computer and use it in GitHub Desktop.
%{
/* Deklaracje dla C */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define YYDEBUG 1
#include "deklaracje.h"
#include "code_generator.h"
/* Ilość błędów */
int errors;
/* Struktura dla etykiet do petli IF, WHILE */
struct lbs
{
int for_goto;
int for_jmp_false;
};
/* Inicjalizacja nowej struktury */
struct lbs * newlblrec()
{
/* malloc zwraca *void więc należy rzutować na strukturę ponownie */
return (struct lbs *) malloc(sizeof(struct lbs));
}
/* Deklaracja zmiennej */
declare(char *name)
{
zmienne *identifier;
identifier = czyZadeklarowane(name); //check if prevoiusly declared
if (identifier == 0)
{
identifier = dodajDeklaracje(name);
}
else
{
errors++;
printf("%s jest zdeklarowany\n", name);
}
}
/* Sprawdzenie zadeklarowania */
context_check(char *command, char *name)
{
zmienne *identifier;
identifier = czyZadeklarowane(name);
if(identifier == 0)
{
errors++;
printf("%s nie jest zdeklarowany\n", name);
}
else
{
generujKod(command, identifier->numerRejestru);
}
}
%}
%union semrec
{
int intval;
char *id;
struct lbs *lbls;
}
%start program
%token <intval> NUMBER
%token <id> IDENTIFIER
%token <lbls> IF WHILE
%token THEN ELSE DO END
%token READ PRINT VAR START
%token ASSIGN
%left EQ NEQ LT GT LTEQ GTEQ
%left '-' '+'
%left '*' '/'
%%
program : VAR
declarations
START
commands
END { generujKod("HALT", -1); YYACCEPT; }
;
declarations : /* empty */
| id_seq IDENTIFIER { declare($2); }
;
id_seq : /* empty */
| id_seq IDENTIFIER { declare($2); }
;
commands : commands command
|
;
command : IDENTIFIER ASSIGN exp ';' { context_check("STORE", $1); }
| READ IDENTIFIER ';' { context_check("READ", $2); }
| PRINT IDENTIFIER ';' { context_check("PRINT", $2); }
| PRINT NUMBER ';' {
generujKod("ZERO", -1);
generujKod("ADDC", $2);
context_check("STORE", "#print0");
context_check("PRINT", "#print0")
}
| IF condition {
$1 = (struct lbs *) newlblrec();
$1->for_jmp_false = rezerwujMiejsce();
}
THEN commands {
$1->for_goto = rezerwujMiejsce(); }
ELSE {
back_patch($1->for_jmp_false, "JGE", generujEtykiete()); }
commands
END {
back_patch($1->for_goto, "JUMP", generujEtykiete()); }
| WHILE {
$1 = (struct lbs *) newlblrec();
$1->for_goto = generujEtykiete();
}
condition { $1->for_jmp_false = rezerwujMiejsce(); }
DO
commands
END {
generujKod("JUMP", $1->for_goto );
back_patch( $1->for_jmp_false, "JGE", generujEtykiete());
}
;
exp : NUMBER { generujKod("ZERO", -1);
generujKod("ADDC", $1);
}
| IDENTIFIER { context_check("LOAD", $1); }
| NUMBER '+' NUMBER { generujKod("ZERO", -1);
generujKod("ADDC", $1);
generujKod("ADDC", $3);
}
| IDENTIFIER '+' IDENTIFIER { context_check("LOAD", $1);
context_check("ADD", $3);
}
| IDENTIFIER '+' NUMBER { context_check("LOAD", $1);
generujKod("ADDC", $3);
}
| NUMBER '+' IDENTIFIER { generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("ADD", $3);
}
| NUMBER '-' NUMBER { generujKod("ZERO", -1);
generujKod("ADDC", $1);
generujKod("SUBC", $3);
}
| IDENTIFIER '-' IDENTIFIER { context_check("LOAD", $1);
context_check("SUB", $3);
}
| IDENTIFIER '-' NUMBER { context_check("LOAD", $1);
generujKod("SUBC", $3);
}
| NUMBER '-' IDENTIFIER { generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("SUB", $3);
}
| NUMBER '*' NUMBER { generujKod("ZERO",-1);
generujKod("ADDC", ($1*$3));}
| NUMBER '*' IDENTIFIER {
if($1==0)
generujKod("ZERO",-1);
else if ($1==1)
context_check("LOAD",$3);
else
{
}
}
| IDENTIFIER '*' NUMBER {
if($3==0)
{
generujKod("ZERO",-1);
}
else if ($3==1)
{
context_check("LOAD",$1);
}
else
{
}
}
| IDENTIFIER '*' IDENTIFIER {
generujKod("ZERO", -1);
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
context_check("LOAD", $3);
context_check("STORE", "xC");
context_check("LOAD", "#jeden");
context_check("STORE", "xD");
context_check("ADD", "xD");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+10);
context_check("LOAD", "xC");
context_check("ADD", "xC");
context_check("STORE", "xC");
context_check("LOAD", "xD");
context_check("ADD", "xD");
context_check("STORE", "xD");
context_check("LOAD", "xD");
context_check("ADD", "xD");
generujKod("JUMP", generujEtykiete()-10);
context_check("LOAD", "xB");
context_check("SUB", "xD");
context_check("STORE", "xB");
context_check("LOAD", "xC");
context_check("ADD", "xA");
context_check("STORE", "xA");
generujKod("ZERO", -1);
context_check("ADD", "xB");
generujKod("JZ", generujEtykiete()+4);
context_check("LOAD", $3);
context_check("STORE", "xC");
generujKod("JUMP", generujEtykiete()-25);
context_check("LOAD", "xA");
}
| NUMBER '/' NUMBER {
if($3==0)
{
generujKod("ZERO",-1);
}
else if($1/$3<=0)
generujKod("ZERO",-1);
else
{
generujKod("ZERO",-1);
generujKod("ADDC", ($1/$3));
}
}
| NUMBER '/' IDENTIFIER
{
if($1==0)
generujKod("ZERO",-1);
else
{
}
}
| IDENTIFIER '/' NUMBER
{
if($3==0)
generujKod("ZERO",-1);
else if($3==1)
context_check("LOAD", $1);
else
{
}
}
| IDENTIFIER '/' IDENTIFIER {
generujKod("ZERO", -1);
context_check("ADD", $3);
generujKod("JZ", generujEtykiete()+32);
context_check("STORE", "xB");
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "#jeden");
context_check("STORE", "xD");
context_check("LOAD", $3);
context_check("STORE", "xC");
context_check("ADD", "xC");
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+9);
context_check("LOAD", "xD");
context_check("ADD", "xD");
context_check("STORE", "xD");
context_check("LOAD", "xC");
context_check("ADD", "xC");
context_check("STORE", "xC");
context_check("ADD", "xC");
generujKod("JUMP", generujEtykiete()-9); //
context_check("LOAD", "xC");
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+7);
context_check("LOAD", "xA");
context_check("SUB", "xC");
context_check("STORE", "xA");
context_check("LOAD", "xB");
context_check("ADD", "xD");
context_check("STORE", "xB");
context_check("LOAD", $3);
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+4);
generujKod("JUMP", generujEtykiete()-27);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "xB");
context_check("SUB", $3);
}
| NUMBER '%' NUMBER {
generujKod("LOAD", $1 % $3);
}
| NUMBER '%' IDENTIFIER {
}
| IDENTIFIER '%' NUMBER {
}
| IDENTIFIER '%' IDENTIFIER {
generujKod("ZERO", -1);
context_check("STORE", "xB");
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "#jeden");
context_check("STORE", "xD");
context_check("LOAD", $3);
context_check("STORE", "xC");
context_check("ADD", "xC");
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+9);
context_check("LOAD", "xD");
context_check("ADD", "xD");
context_check("STORE", "xD");
context_check("LOAD", "xC");
context_check("ADD", "xC");
context_check("STORE", "xC");
context_check("ADD", "xC");
generujKod("JUMP", generujEtykiete()-9); //
context_check("LOAD", "xC");
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+7);
context_check("LOAD", "xA");
context_check("SUB", "xC");
context_check("STORE", "xA");
context_check("LOAD", "xB");
context_check("ADD", "xD");
context_check("STORE", "xB");
context_check("LOAD", $3);
context_check("SUB", "xA");
generujKod("JGE", generujEtykiete()+2);
generujKod("JUMP", generujEtykiete()-27);
context_check("LOAD", "xA");
}
;
condition : NUMBER EQ NUMBER {
if($1 == $3)
{
generujKod("ZERO", -1);
}
else
{
generujKod("ZERO", -1);
generujKod("ADDC", 1);
}
}
| NUMBER EQ IDENTIFIER {
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("STORE", "xC");
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER EQ NUMBER {
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("STORE", "xC");
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER EQ IDENTIFIER {
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
/* Tutaj if */
}
| NUMBER NEQ NUMBER {
if($1 == $3)
{
context_check("LOAD", "#jeden");
}
else
{
generujKod("ZERO", -1);
}
}
| NUMBER NEQ IDENTIFIER {
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("STORE", "xC");
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| IDENTIFIER NEQ NUMBER {
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("STORE", "xC");
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| IDENTIFIER NEQ IDENTIFIER {
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
/* Tutaj if */
}
| NUMBER LT NUMBER {
if($1 < $3)
generujKod("ZERO", -1);
else
context_check("LOAD", "#jeden");
}
| NUMBER LT IDENTIFIER {;
context_check("LOAD", $3);
generujKod("SUBC", $1);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
/* if */
}
| IDENTIFIER LT NUMBER {
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| IDENTIFIER LT IDENTIFIER {
context_check("LOAD", $3);
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| NUMBER GT NUMBER {
if($1 > $3)
generujKod("ZERO", -1);
else
context_check("LOAD", "#jeden");
}
| NUMBER GT IDENTIFIER {
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| IDENTIFIER GT NUMBER {
context_check("LOAD", $1);
generujKod("SUBC", $3);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| IDENTIFIER GT IDENTIFIER {
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+3); /* Większe */
context_check("LOAD", "#jeden");
generujKod("JUMP", generujEtykiete()+2);
generujKod("ZERO", -1);
}
| NUMBER LTEQ NUMBER {
if($1 <= $3)
generujKod("ZERO", -1);
else
context_check("LOAD", "#jeden");
}
| NUMBER LTEQ IDENTIFIER {
context_check("LOAD", $3);
generujKod("SUBC", $1);
generujKod("JGE", generujEtykiete()+18); /* Większe to bedzie koniec */
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("STORE", "xC");
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER LTEQ NUMBER {
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+18); /* Większe */
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("STORE", "xC");
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER LTEQ IDENTIFIER {
context_check("LOAD", $3);
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+16); /* Większe */
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| NUMBER GTEQ NUMBER {
if($1 >= $3)
generujKod("ZERO", -1);
else
context_check("LOAD", "#jeden");
}
| NUMBER GTEQ IDENTIFIER {
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+18); /* Większe */
generujKod("ZERO", -1);
generujKod("ADDC", $1);
context_check("STORE", "xC");
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER GTEQ NUMBER {
context_check("LOAD", $1);
generujKod("SUBC", $3);
generujKod("JGE", generujEtykiete()+18); /* Większe */
generujKod("ZERO", -1);
generujKod("ADDC", $3);
context_check("STORE", "xC");
context_check("SUB", $1);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", "xC");
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", "xC");
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
| IDENTIFIER GTEQ IDENTIFIER {
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+16); /* Większe */
context_check("LOAD", $1);
context_check("SUB", $3);
generujKod("JGE", generujEtykiete()+6); /* Jak wieksze to niech bedzie z lewej strony */
context_check("LOAD", $3);
context_check("STORE", "xA");
context_check("LOAD", $1);
context_check("STORE", "xB");
generujKod("JUMP", generujEtykiete()+5);
context_check("LOAD", $1);
context_check("STORE", "xA");
context_check("LOAD", $3);
context_check("STORE", "xB");
context_check("LOAD", "xA");
context_check("SUB", "xB");
generujKod("JGE", generujEtykiete()+3);
generujKod("ZERO", -1);
generujKod("JUMP", generujEtykiete()+2);
context_check("LOAD", "#jeden");
}
;
%%
/* Odpalanie parsera */
int main(int argc, char *argv[])
{
extern FILE *yyin;
yyin = fopen(argv[1], "r");
errors = 0;
declare("#print0"); /* Wyświetlanie */
declare("#jeden");
declare("xA");
declare("xB");
declare("xC");
declare("xD");
generujKod("ADDC", 1);
context_check("STORE", "#jeden");
extern int yydebug;
yydebug = 0;
yyparse();
if(errors == 0)
{
printCommand();
}
return 0;
}
yyerror(char *s)
{
errors++;
printf("%s\n", s);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment