Skip to content

Commit 5ebfb5d

Browse files
committed
PARSER
1 parent e1ecc1b commit 5ebfb5d

File tree

2 files changed

+318
-0
lines changed

2 files changed

+318
-0
lines changed

src/Parser.cpp

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
#include "Parser.h"
2+
3+
namespace FPL {
4+
Parser::Parser() {
5+
mTypes["vide"] = Type("vide", VOID);
6+
mTypes["entier"] = Type("entier", INT);
7+
mTypes["decimal"] = Type("decimal", DOUBLE);
8+
mTypes["texte"] = Type("texte", STRING);
9+
}
10+
11+
bool Parser::FunctionChecker() {
12+
auto parseStart = mCurrentToken; // std::vector<Token>::iterator
13+
auto PeutEtreInstruction = CheckerIdentifiant();
14+
if (PeutEtreInstruction.has_value()) {
15+
// On a une instruction
16+
if (PeutEtreInstruction->mText == "definir") { // On vérifie si l'instruction est une fonction
17+
auto PeutEtreNom = CheckerIdentifiant();
18+
if (PeutEtreNom.has_value()) {
19+
// On a le nom d'une fonction.
20+
if (CheckerOperateur("(").has_value()) {
21+
//On a surement une fonction finie !
22+
23+
FonctionDefinition fonction;
24+
fonction.FonctionName = PeutEtreNom->mText;
25+
26+
while (CheckerOperateur(")") == std::nullopt) {
27+
auto type = CheckerType();
28+
29+
// Si aucun paramètre ou l'utilisateur a utilisé l'argument 'vide' ou juste fermer.
30+
if (type->mType == VOID) { break; }
31+
32+
if (!type.has_value() || type == std::nullopt) {
33+
throw std::runtime_error("Vous devez spécifier un type d'argument.");
34+
}
35+
36+
// Ajout de l'argument...
37+
auto variableName = CheckerIdentifiant();
38+
if (!variableName.has_value()) {
39+
throw std::runtime_error("Vous devez spécifier un nom unique à l'argument.");
40+
}
41+
ArgumentDefinition param;
42+
param.ArgType.mName = type->mName;
43+
param.ArgType.mType = type->mType;
44+
param.ArgName = variableName->mText;
45+
fonction.ArgsFonction.push_back(param);
46+
47+
if (CheckerOperateur(")").has_value()) {
48+
break;
49+
}
50+
if (!CheckerOperateur(",").has_value()) {
51+
throw std::runtime_error(
52+
"Vous devez utiliser la ',' pour separer les arguments de la fonction.");
53+
}
54+
}
55+
56+
mFonctions[fonction.FonctionName] = fonction;
57+
58+
// On récupère le code entre les {} :
59+
60+
if (CheckerOperateur("{")) {
61+
while (!CheckerOperateur("}").has_value()) {
62+
fonction.FonctionContent.push_back(mCurrentToken->mText);
63+
++mCurrentToken;
64+
65+
if (CheckerOperateur("}").has_value()) {
66+
break;
67+
}
68+
}
69+
70+
}
71+
72+
return true;
73+
} else {
74+
mCurrentToken = parseStart;
75+
std::cerr
76+
<< "Vous devez ouvrir les parenthèses pour ajouter des paramètres si vous le souhaitez."
77+
<< std::endl;
78+
}
79+
} else {
80+
mCurrentToken = parseStart;
81+
std::cerr << "Vous devez donner un nom à votre fonction." << std::endl;
82+
}
83+
} else {
84+
mCurrentToken = parseStart;
85+
}
86+
}
87+
return false;
88+
}
89+
90+
91+
bool Parser::PrintStat() {
92+
auto parseStart = mCurrentToken; // std::vector<Token>::iterator
93+
auto PeutEtreInstruction = CheckerIdentifiant();
94+
if (PeutEtreInstruction.has_value()) {
95+
if (PeutEtreInstruction->mText == "envoyer") {
96+
auto ChaineEnter = CheckerChaineLitteral();
97+
if (ChaineEnter.has_value()) {
98+
std::string printContent = ChaineEnter->mText;
99+
std::replace(printContent.begin(), printContent.end(), '"', ' ');
100+
std::cout << printContent;
101+
std::cout << std::endl;
102+
return true;
103+
} else {
104+
std::cerr
105+
<< "Vous devez mettre des \" pour ouvrir et fermer l'instruction que si le type est texte."
106+
<< std::endl;
107+
mCurrentToken = parseStart;
108+
}
109+
}
110+
}
111+
return false;
112+
}
113+
114+
bool Parser::VariableDeclaration() {
115+
auto parseStart = mCurrentToken; // std::vector<Token>::iterator
116+
auto PeutEtreInstruction = CheckerIdentifiant();
117+
if (PeutEtreInstruction.has_value() && PeutEtreInstruction->mText == "variable") {
118+
auto pType = CheckerType();
119+
if (pType.has_value()) {
120+
if (pType->mType == VOID) {
121+
std::cerr << "Le type 'vide' n'est pas possible pour une variable." << std::endl;
122+
mCurrentToken = parseStart;
123+
}
124+
125+
auto pName = CheckerIdentifiant();
126+
if (pName.has_value()) {
127+
128+
if (CheckerOperateur("-").has_value()) {
129+
if (CheckerOperateur(">").has_value()) {
130+
auto pValue = CheckerValue();
131+
if (pValue.has_value()) {
132+
//VariableDefinition variable(pName->mText, pType->mName, pType->mType);
133+
VariableDefinition variable;
134+
variable.VariableName = pName->mText;
135+
variable.VariableType = Type(pType->mName, pType->mType);
136+
variable.GiveValue(mCurrentToken->mText);
137+
138+
mVariables[variable.VariableName] = variable;
139+
return true;
140+
} else {
141+
throw std::runtime_error("Vous devez donner une valeur a votre variable.");
142+
}
143+
} else {
144+
throw std::runtime_error("Pour donner la valeur à votre variable, merci d'utiliser '->'.");
145+
}
146+
} else {
147+
throw std::runtime_error("Pour donner la valeur à votre variable, merci d'utiliser '->'.");
148+
}
149+
} else {
150+
std::cerr << "Vous devez donner un nom à votre variable." << std::endl;
151+
mCurrentToken = parseStart;
152+
}
153+
} else {
154+
std::cerr << "Vous devez mettre le type de votre variable." << std::endl;
155+
mCurrentToken = parseStart;
156+
}
157+
}
158+
return false;
159+
}
160+
161+
162+
void Parser::parse(std::vector<Token> &tokens) {
163+
mEndToken = tokens.end();
164+
mCurrentToken = tokens.begin();
165+
166+
while (mCurrentToken != mEndToken) { // Tant que tout le fichier n'est pas parcouru et qu'on n'a pas analysé tous les éléments.
167+
if (FunctionChecker()) {
168+
169+
}
170+
171+
if (PrintStat()) {
172+
173+
}
174+
175+
if (VariableDeclaration()) {
176+
177+
} else {
178+
if (mCurrentToken->mText.empty()) {
179+
continue;
180+
}
181+
std::cerr << "Identifier inconnu : " << Parser::mCurrentToken->mText << std::endl;
182+
++mCurrentToken;
183+
}
184+
}
185+
}
186+
187+
std::optional<Token> Parser::CheckerChaineLitteral(const std::string &name) {
188+
if (mCurrentToken == mEndToken) { return std::nullopt; }
189+
if (mCurrentToken->mType != CHAINE_LITERAL) { return std::nullopt; }
190+
if (mCurrentToken->mText != name && !name.empty()) { return std::nullopt; }
191+
192+
auto returnToken = mCurrentToken;
193+
++mCurrentToken;
194+
return *returnToken;
195+
}
196+
197+
std::optional<Token> Parser::CheckerIdentifiant(const std::string &name) {
198+
if (mCurrentToken == mEndToken) { return std::nullopt; }
199+
if (mCurrentToken->mType != IDENTIFIANT) { return std::nullopt; }
200+
if (mCurrentToken->mText != name && !name.empty()) { return std::nullopt; }
201+
202+
auto returnToken = mCurrentToken;
203+
++mCurrentToken;
204+
return *returnToken;
205+
}
206+
207+
std::optional<Token> Parser::CheckerOperateur(const std::string &name) {
208+
if (mCurrentToken == mEndToken) { return std::nullopt; }
209+
if (mCurrentToken->mType != OPERATEUR) { return std::nullopt; }
210+
if (mCurrentToken->mText != name && !name.empty()) { return std::nullopt; }
211+
// On vérifie s'il est présent, si c'est un OPERATEUR et que c'est le bon nom.
212+
213+
auto returnToken = mCurrentToken; // std::vector<Token>::iterator
214+
++mCurrentToken;
215+
return *returnToken; // On donne l'opérateur
216+
}
217+
218+
std::optional<Type> Parser::CheckerType(const std::string &name) {
219+
auto possibleType = CheckerIdentifiant();
220+
if (!possibleType.has_value()) { return std::nullopt; }
221+
222+
auto foundType = mTypes.find(possibleType->mText);
223+
if (foundType == mTypes.end()) {
224+
--mCurrentToken;
225+
return std::nullopt;
226+
}
227+
228+
return foundType->second;
229+
}
230+
231+
std::optional<Statement> Parser::CheckerValue()
232+
{
233+
std::optional<Statement> res;
234+
if (mCurrentToken->mType == DECIMAL_LITERAL)
235+
{
236+
Statement doubleLitteralStatement (StatementKind::LITTERAL, mCurrentToken->mText, Type("decimal", DOUBLE));
237+
res = doubleLitteralStatement;
238+
++mCurrentToken;
239+
}
240+
else if (mCurrentToken->mType == ENTIER_LITERAL)
241+
{
242+
Statement integerLitteralStatement(StatementKind::LITTERAL, mCurrentToken->mText, Type("entier", INT));
243+
res = integerLitteralStatement;
244+
++mCurrentToken;
245+
}
246+
else if (mCurrentToken->mType == CHAINE_LITERAL)
247+
{
248+
Statement stringLitteralStatement(StatementKind::LITTERAL, mCurrentToken->mText, Type("text", STRING));
249+
res = stringLitteralStatement;
250+
++mCurrentToken;
251+
} else {
252+
return std::nullopt;
253+
}
254+
255+
return res;
256+
}
257+
258+
259+
void Parser::DebugPrint() const {
260+
for (auto &funcPair: mFonctions) {
261+
for (auto &e: funcPair.second.FonctionContent) {
262+
std::cout << e << std::endl;
263+
}
264+
}
265+
}
266+
}

src/Parser.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include <iostream>
4+
#include <vector>
5+
#include <string>
6+
#include <stdexcept>
7+
#include <optional>
8+
#include <map>
9+
#include <algorithm>
10+
11+
#include "TokenBuilding.h"
12+
#include "TypeManager.h"
13+
#include "FonctionDefinition.h"
14+
#include "VariableDefinition.h"
15+
16+
namespace FPL {
17+
18+
class Parser {
19+
public:
20+
Parser();
21+
22+
void parse(std::vector<Token> &tokens);
23+
24+
void DebugPrint() const;
25+
26+
private:
27+
// Essentielles:
28+
std::optional<Type> CheckerType(const std::string &name = std::string());
29+
std::optional<Token> CheckerIdentifiant(const std::string &name = std::string());
30+
std::optional<Token> CheckerOperateur(const std::string &name = std::string());
31+
std::optional<Token> CheckerChaineLitteral(const std::string &name = std::string());
32+
std::optional<Statement> CheckerValue();
33+
34+
35+
// Print :
36+
bool PrintStat();
37+
38+
// Variable :
39+
bool VariableDeclaration();
40+
std::map<std::string, VariableDefinition> mVariables;
41+
42+
// Fonctions :
43+
bool FunctionChecker();
44+
std::map<std::string, FonctionDefinition> mFonctions;
45+
46+
47+
// Utils :
48+
std::vector<Token>::iterator mCurrentToken;
49+
std::vector<Token>::iterator mEndToken;
50+
std::map<std::string, Type> mTypes;
51+
};
52+
}

0 commit comments

Comments
 (0)