Commit f6c2d656 authored by qanastek's avatar qanastek

update post backup de l'uapv

parent 58867e23
# CERIcompiler :computer: # CERIcompiler
*Author: Labrak Yanis*
*Degree: Licence 2 Informatique - Groupe 4*
*School: Université d'Avignon*
**Task List :**
- [x] Initialize the project
- [x] LL(1)
- [x] Modify Main
- [x] Create function OperatorComparaison()
- [x] Create function Comparaison()
- [x] Check result of the compilator
- [x] Numbers
- [ ] Mul / Div
- [ ] Program
- [x] DeclarationPart
- [ ] Statements
- [ ] if
- [ ] while
- [ ] do while
- [ ] for
- [ ] AssignementStatement - A = B
- [ ] LL(2)
- [x] Read next char
- [ ] MultiplicativeOperator
- [ ] RelationalOperator
- [ ] AdditiveOperator
**Errors to fix :**
- [ ] Cannot do (a+2)
**Compile, inject the arithmetic expression in the program and check functionement in DDD**
> g++ -ggdb compilateur.cpp -o compilateur && cat test.p | ./compilateur > test.s && gcc -ggdb test.s -o test && ddd ./test
**Program working diagram :** *(So big to be fully modelized)*
```mermaid
graph TD;
input_expression-->ReadChar;
ReadChar-->CheckSign;
CheckSign-->ReadChar;
CheckSign-->Error;
ReadChar-->Stop;
ReadChar-->Comparaison;
Comparaison-->ReadChar;
Comparaison-->ArithmeticExpression;
ArithmeticExpression-->Term;
Term-->IfParemthese;
Term-->IfNotParemthese;
IfParemthese-->ReadChar;
IfParemthese-->ArithmeticExpression;
```
>>>
A simple compiler.
From : `Pascal`-like imperative LL(k) langage
To : 64 bit 80x86 assembly langage (`AT&T`)
>>>
# Usage Informations A simple compiler.
From : Pascal-like imperative LL(k) langage
To : 64 bit 80x86 assembly langage (AT&T)
**Download the repository :** **Download the repository :**
> git clone https://framagit.org/qanastek/cericompiler > git clone git@framagit.org:jourlin/cericompiler.git
**Build the compiler with debug symbols :**
> g++ -ggdb compilateur.cpp -o compilateur **Build the compiler and test it :**
**Compile the test program :** > make test
> cat test.p | ./compilateur > test.s
**Have a look at the output :** **Have a look at the output :**
> gedit test.s > gedit test.s
**Produce the executable (with debug info) :**
> gcc -ggdb test.s -o test :
**Debug the executable :** **Debug the executable :**
> ddd ./test > ddd ./test
...@@ -103,3 +32,24 @@ To : 64 bit 80x86 assembly langage (`AT&T`) ...@@ -103,3 +32,24 @@ To : 64 bit 80x86 assembly langage (`AT&T`)
> git pull -u origin master > git pull -u origin master
**This version Can handle :**
// Program := [DeclarationPart] StatementPart
// DeclarationPart := "[" Identifier {"," Identifier} "]"
// StatementPart := Statement {";" Statement} "."
// Statement := AssignementStatement
// AssignementStatement := Identifier ":=" Expression
// Expression := SimpleExpression [RelationalOperator SimpleExpression]
// SimpleExpression := Term {AdditiveOperator Term}
// Term := Factor {MultiplicativeOperator Factor}
// Factor := Number | Letter | "(" Expression ")"| "!" Factor
// Number := Digit{Digit}
// Identifier := Letter {(Letter|Digit)}
// AdditiveOperator := "+" | "-" | "||"
// MultiplicativeOperator := "*" | "/" | "%" | "&&"
// RelationalOperator := "==" | "!=" | "<" | ">" | "<=" | ">="
// Digit := "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
// Letter := "a"|...|"z"
No preview for this file type
...@@ -21,446 +21,504 @@ ...@@ -21,446 +21,504 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <algorithm> #include <set>
#include <map>
#include <FlexLexer.h>
#include "tokeniser.h"
#include <cstring>
using namespace std; using namespace std;
char current, lookedAhead; // Current char enum OPREL {EQU, DIFF, INF, SUP, INFE, SUPE, WTFR};
int NLookedAhead=0; enum OPADD {ADD, SUB, OR, WTFA};
enum OPMUL {MUL, DIV, MOD, AND ,WTFM};
void ReadChar(void){ enum TYPES {INTEGER, BOOLEAN};
if(NLookedAhead>0){
current=lookedAhead; // Char has already been read
NLookedAhead--;
}
else
// Read character and skip spaces until
// non space character is read
while(cin.get(current) && (current==' '||current=='\t'||current=='\n'));
}
void LookAhead(void) TOKEN current; // Current token
{
while(cin.get(lookedAhead) && (lookedAhead==' '||lookedAhead=='\t'||lookedAhead=='\n'));
NLookedAhead++;
}
void Error(string s)
{ FlexLexer* lexer = new yyFlexLexer; // This is the flex tokeniser
cerr << s << endl; // tokens can be read using lexer->yylex()
exit(-1); // lexer->yylex() returns the type of the lexicon entry (see enum TOKEN in tokeniser.h)
// and lexer->YYText() returns the lexicon entry as a string
map<string, enum TYPES> DeclaredVariables; // Store declared variables and their types
unsigned long long TagNumber=0;
bool IsDeclared(const char *id){
return DeclaredVariables.find(id)!=DeclaredVariables.end();
} }
/**
* Return if its a digit or not void Error(string s){
* @param C Character to analyze cerr << "Ligne n°"<<lexer->lineno()<<", lu : '"<<lexer->YYText()<<"'("<<current<<"), mais ";
* @return true or false cerr<< s << endl;
*/ exit(-1);
bool isDigit(char C)
{
if (C >= '0' and C <= '9')
{
return true;
}
else
{
return false;
}
} }
/** // Program := [DeclarationPart] StatementPart
* Return if its a letter or not // DeclarationPart := "[" Letter {"," Letter} "]"
* @param C Character to analyze // StatementPart := Statement {";" Statement} "."
* @return true or false // Statement := AssignementStatement
*/ // AssignementStatement := Letter "=" Expression
bool isLetter(char C)
{ // Expression := SimpleExpression [RelationalOperator SimpleExpression]
if (C >= 'A' and C <= 'Z') // SimpleExpression := Term {AdditiveOperator Term}
{ // Term := Factor {MultiplicativeOperator Factor}
return true; // Factor := Number | Letter | "(" Expression ")"| "!" Factor
} // Number := Digit{Digit}
else if (C >= 'a' and C <= 'z')
{ // AdditiveOperator := "+" | "-" | "||"
return true; // MultiplicativeOperator := "*" | "/" | "%" | "&&"
} // RelationalOperator := "==" | "!=" | "<" | ">" | "<=" | ">="
else // Digit := "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
{ // Letter := "a"|...|"z"
return false;
} // To avoid cross references problems :
enum TYPES Expression(void); // Called by Term() and calls Term()
void Statement(void);
void StatementPart(void);
enum TYPES Identifier(void){
cout << "\tpush "<<lexer->YYText()<<endl;
current=(TOKEN) lexer->yylex();
return INTEGER;
} }
/** enum TYPES Number(void){
* Return if its a additif operator or not cout <<"\tpush $"<<atoi(lexer->YYText())<<endl;
* @param C Character to analyze current=(TOKEN) lexer->yylex();
* @return true or false return INTEGER;
*/
bool isAddOpp(char C)
{
if (C == '+' or C == '-')
{
return true;
}
else
{
return false;
}
} }
bool isCompOpp(char C) enum TYPES Factor(void){
{ enum TYPES type;
if (current == '<' or current == '>' or current == '!' or current == '=') if(current==RPARENT){
{ current=(TOKEN) lexer->yylex();
return true; type=Expression();
} if(current!=LPARENT)
else Error("')' était attendu"); // ")" expected
{ else
return false; current=(TOKEN) lexer->yylex();
} }
else
if (current==NUMBER)
type=Number();
else
if(current==ID)
type=Identifier();
else
Error("'(' ou chiffre ou lettre attendue");
return type;
} }
/** // MultiplicativeOperator := "*" | "/" | "%" | "&&"
* Convert an Character to an Integer OPMUL MultiplicativeOperator(void){
* @param C The char you want to convert OPMUL opmul;
* @return Integer if(strcmp(lexer->YYText(),"*")==0)
*/ opmul=MUL;
int CharToInt(char C) else if(strcmp(lexer->YYText(),"/")==0)
{ opmul=DIV;
return C - '0'; else if(strcmp(lexer->YYText(),"%")==0)
opmul=MOD;
else if(strcmp(lexer->YYText(),"&&")==0)
opmul=AND;
else opmul=WTFM;
current=(TOKEN) lexer->yylex();
return opmul;
} }
// int toInteger(string leNombre) // Term := Factor {MultiplicativeOperator Factor}
// { enum TYPES Term(void){
// unsigned long long nbr; TYPES type1, type2;
// stringStream laConversion(leNombre); OPMUL mulop;
// laConversion >> nbr; type1=Factor();
while(current==MULOP){
// return nbr; mulop=MultiplicativeOperator(); // Save operator in local variable
// } type2=Factor();
if(type2!=type1)
// ArithmeticExpression := Term {AdditiveOperator Term} Error("types incompatibles dans l'expression");
// Term := Digit | "(" ArithmeticExpression ")" cout << "\tpop %rbx"<<endl; // get first operand
// AdditiveOperator := "+" | "-" cout << "\tpop %rax"<<endl; // get second operand
// ComparaisonOperator := "<" | ">" | "=" switch(mulop){
// Digit := "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" case AND:
if(type2!=BOOLEAN)
void AdditiveOperator(void) Error("le type doit être BOOLEAN dans l'expression");
{ cout << "\tmulq %rbx"<<endl; // a * b -> %rdx:%rax
if(current == '+' or current == '-') cout << "\tpush %rax\t# AND"<<endl; // store result
{ break;
ReadChar(); case MUL:
} if(type2!=INTEGER)
else Error("le type doit être INTEGER dans l'expression");
{ cout << "\tmulq %rbx"<<endl; // a * b -> %rdx:%rax
Error("Opérateur additif attendu"); // Additive operator expected cout << "\tpush %rax\t# MUL"<<endl; // store result
break;
case DIV:
if(type2!=INTEGER)
Error("le type doit être INTEGER dans l'expression");
cout << "\tmovq $0, %rdx"<<endl; // Higher part of numerator
cout << "\tdiv %rbx"<<endl; // quotient goes to %rax
cout << "\tpush %rax\t# DIV"<<endl; // store result
break;
case MOD:
if(type2!=INTEGER)
Error("le type doit être INTEGER dans l'expression");
cout << "\tmovq $0, %rdx"<<endl; // Higher part of numerator
cout << "\tdiv %rbx"<<endl; // remainder goes to %rdx
cout << "\tpush %rdx\t# MOD"<<endl; // store result
break;
default:
Error("opérateur multiplicatif attendu");
}
} }
return type1;
} }
void OperatorComparaison(void) // AdditiveOperator := "+" | "-" | "||"
{ OPADD AdditiveOperator(void){
if(isCompOpp(current)) OPADD opadd;
{ if(strcmp(lexer->YYText(),"+")==0)
ReadChar(); opadd=ADD;
} else if(strcmp(lexer->YYText(),"-")==0)
else opadd=SUB;
{ else if(strcmp(lexer->YYText(),"||")==0)
Error("Opérateur comparaison attendu"); // Additive operator expected opadd=OR;
} else opadd=WTFA;
current=(TOKEN) lexer->yylex();
return opadd;
} }
void Declaration() // SimpleExpression := Term {AdditiveOperator Term}
{ enum TYPES SimpleExpression(void){
cout << "\t.data" << endl; enum TYPES type1, type2;
cout << "\t.align 8"<<endl; OPADD adop;
type1=Term();
if (isLetter(current)) while(current==ADDOP){
{ adop=AdditiveOperator(); // Save operator in local variable
cout << current << ":\t.quad 0" << endl; type2=Term();
if(type2!=type1)
LookAhead(); Error("types incompatibles dans l'expression");
cout << "\tpop %rbx"<<endl; // get first operand
while (lookedAhead != ']') cout << "\tpop %rax"<<endl; // get second operand
{ switch(adop){
if (lookedAhead == ',') case OR:
{ if(type2!=BOOLEAN)
ReadChar(); Error("le type doit être BOOLEAN dans l'expression");
} cout << "\taddq %rbx, %rax\t# OR"<<endl;// operand1 OR operand2
else if (isLetter(lookedAhead)) break;
{ case ADD:
ReadChar(); if(type2!=INTEGER)
cout << current << ":\t.quad 0" << endl; Error("le type doit être INTEGER dans l'expression");
} cout << "\taddq %rbx, %rax\t# ADD"<<endl; // add both operands
LookAhead(); break;
case SUB:
if(type2!=INTEGER)
Error("le type doit être INTEGER dans l'expression");
cout << "\tsubq %rbx, %rax\t# SUB"<<endl; // substract both operands
break;
default:
Error("opérateur additif inconnu");
} }
cout << "\tpush %rax"<<endl; // store result
ReadChar();
}
else
{
Error("Letter expected");
} }
return type1;
} }
void Digit(void) // DeclarationPart := "[" Ident {"," Ident} "]"
{ void DeclarationPart(void){
if(!isDigit(current)) if(current!=RBRACKET)
{ Error("caractère '[' attendu");
Error("Chiffre attendu"); // Digit expected current=(TOKEN) lexer->yylex();
if(current!=ID)
Error("Un identificater était attendu");
cout << lexer->YYText() << ":\t.quad 0"<<endl;
DeclaredVariables[lexer->YYText()]=INTEGER;
current=(TOKEN) lexer->yylex();
while(current==COMMA){
current=(TOKEN) lexer->yylex();
if(current!=ID)
Error("Un identificateur était attendu");
cout << lexer->YYText() << ":\t.quad 0"<<endl;
DeclaredVariables[lexer->YYText()]=INTEGER;
current=(TOKEN) lexer->yylex();
} }
else if(current!=LBRACKET)
{ Error("caractère ']' attendu");
unsigned long long num = CharToInt(current); current=(TOKEN) lexer->yylex();
}
ReadChar(); // RelationalOperator := "==" | "!=" | "<" | ">" | "<=" | ">="
OPREL RelationalOperator(void){
OPREL oprel;
if(strcmp(lexer->YYText(),"==")==0)
oprel=EQU;
else if(strcmp(lexer->YYText(),"!=")==0)
oprel=DIFF;
else if(strcmp(lexer->YYText(),"<")==0)
oprel=INF;
else if(strcmp(lexer->YYText(),">")==0)
oprel=SUP;
else if(strcmp(lexer->YYText(),"<=")==0)
oprel=INFE;
else if(strcmp(lexer->YYText(),">=")==0)
oprel=SUPE;
else oprel=WTFR;
current=(TOKEN) lexer->yylex();
return oprel;
}
while(isDigit(current)) // Expression := SimpleExpression [RelationalOperator SimpleExpression]
{ enum TYPES Expression(void){
num *= 10; // Move curent first digit to the left enum TYPES type1, type2;
num += CharToInt(current); // Add the current digit to it unsigned long long tag;
ReadChar(); // Move to the next one OPREL oprel;
type1=SimpleExpression();
if(current==RELOP){
tag=++TagNumber;
oprel=RelationalOperator();
type2=SimpleExpression();
if(type2!=type1)
Error("types incompatibles pour la comparaison");
cout << "\tpop %rax"<<endl;
cout << "\tpop %rbx"<<endl;
cout << "\tcmpq %rax, %rbx"<<endl;
switch(oprel){
case EQU:
cout << "\tje Vrai"<<tag<<"\t# If equal"<<endl;
break;
case DIFF:
cout << "\tjne Vrai"<<tag<<"\t# If different"<<endl;
break;
case SUPE:
cout << "\tjae Vrai"<<tag<<"\t# If above or equal"<<endl;
break;
case INFE:
cout << "\tjbe Vrai"<<tag<<"\t# If below or equal"<<endl;
break;
case INF:
cout << "\tjb Vrai"<<tag<<"\t# If below"<<endl;
break;
case SUP:
cout << "\tja Vrai"<<tag<<"\t# If above"<<endl;
break;
default:
Error("Opérateur de comparaison inconnu");
} }
cout << "\tpush $0\t\t# False"<<endl;
cout << "\tpush $" << num << endl; // Push the full number cout << "\tjmp Suite"<<tag<<endl;
cout << "Vrai"<<tag<<":\tpush $0xFFFFFFFFFFFFFFFF\t\t# True"<<endl;
cout << "Suite"<<tag<<":"<<endl;
return BOOLEAN;
} }
return type1;
} }
void Variable(void) // AssignementStatement := Identifier ":=" Expression
{ void AssignementStatement(void){
if(!isLetter(current)) enum TYPES type1, type2;
{ string variable;
Error("Lettre attendu"); // Digit expected if(current!=ID)
Error("Identificateur attendu");
if(!IsDeclared(lexer->YYText())){
cerr << "Erreur : Variable '"<<lexer->YYText()<<"' non déclarée"<<endl;
exit(-1);
} }
else variable=lexer->YYText();
{ type1=DeclaredVariables[variable];
cout << "\tpush " << current << "\t# Variable - " << current << endl; // Push the full number current=(TOKEN) lexer->yylex();
if(current!=ASSIGN)
Error("caractères ':=' attendus");
current=(TOKEN) lexer->yylex();
type2=Expression();
if(type2!=type1){
cerr<<"Type variable "<<type1<<endl;
cerr<<"Type Expression "<<type2<<endl;
Error("types incompatibles dans l'affectation");
} }
cout << "\tpop "<<variable<<endl;
} }
void ArithmeticExpression(void); // Called by Term() and calls Term() // DisplayStatement := "DISPLAY" Expression
void DisplayStatement(void){
current=(TOKEN) lexer->yylex();
if(Expression()!=INTEGER)
Error("DISPLAY ne fonctionne que pour les nombres entiers");
cout << "\tpop %rdx\t# The value to be displayed"<<endl;
cout << "\tmovq $FormatString1, %rsi\t# \"%llu\\n\""<<endl;
cout << "\tmovl $1, %edi"<<endl;
cout << "\tmovl $0, %eax"<<endl;
cout << "\tcall __printf_chk@PLT"<<endl;
}
void LoadDeclaration(void) // ForStatement := "For" ID ":=" Expression ("TO"|"DOWNTO") Expression "DO" Statement
void ForStatement(void)
{ {
if (current == '[') unsigned long long tag = TagNumber++;
{
ReadChar();
Declaration(); if (strcmp(lexer->YYText(), "FOR")!=0) Error("FOR expected");
if(current != ']') cout << "ForInit" << tag << ":" << endl;
{
Error("']' expected");
}
else
{
ReadChar();
}
}
}
void Term(void) current = (TOKEN) lexer->yylex();
{
if(current == '(')
{
ReadChar();
ArithmeticExpression(); string variable = lexer->YYText(); // Récupère le nom de la variable
// ReadChar(); AssignementStatement();
// cout << " current : " << current << endl;
if(current != ')') if (strcmp(lexer->YYText(), "TO")!=0) Error("TO expected");
{
Error("')' expected");
}
else
{
ReadChar();
}
}
else
{
if (isDigit(current))
{
Digit();
}
else if (isLetter(current))
{
Variable(); // Push the variable
}
else
{
Error("Letter or '(' or number expected");
}
}
}
void ArithmeticExpression(void) current = (TOKEN) lexer->yylex();
{
char ope;
Term(); Expression();
// ReadChar(); cout << "\tpop %rax" << endl; // Récupère le résultat goal
if (isLetter(current))
{
ReadChar();
}
// cout << " current : " << current << endl;
while (isAddOpp(current)) cout << "For" << tag << " :" << endl;
{
ope = current; // Save operator in local variable
if (isAddOpp(current)) cout << "\tcmpq %rax, " << variable << endl; // Regarde si i respecte le goal
{ cout << "\tjge SuiteFor" << tag << endl; // Si il à dépassé ou il est au goal jump vers SuiteFor
AdditiveOperator();
}
Term(); if (strcmp(lexer->YYText(), "DO")!=0) Error("DO expected");
cout << "\tpop %rbx"<<endl; // get first operand current = (TOKEN) lexer->yylex();
cout << "\tpop %rax"<<endl; // get second operand