AbderFaiz 5 miesięcy temu
rodzic
commit
42ce57606b
7 zmienionych plików z 125 dodań i 34 usunięć
  1. 2 1
      .gitignore
  2. 7 2
      Makefile
  3. 36 0
      src/Emitter.cpp
  4. 16 0
      src/Emitter.hpp
  5. 55 28
      src/Parser.cpp
  6. 5 2
      src/Parser.hpp
  7. 4 1
      src/main.cpp

+ 2 - 1
.gitignore

@@ -31,4 +31,5 @@
 # Executables
 *.exe
 *.out
-*.app
+*.app
+out.c

+ 7 - 2
Makefile

@@ -10,18 +10,23 @@ Token.o : src/Token.cpp src/Token.hpp
 Symbol.o : src/Symbol.cpp src/Symbol.hpp
 	$(CC) -c $(FLAGS) $< 
 
+Emitter.o : src/Emitter.cpp src/Emitter.hpp
+	$(CC) -c $(FLAGS) $< 
+
 Lexer.o : src/Lexer.cpp src/Lexer.hpp Token.o
 	$(CC) -c $(FLAGS) $< 
 
-Parser.o : src/Parser.cpp src/Parser.hpp Lexer.o Token.o Symbol.o
+Parser.o : src/Parser.cpp src/Parser.hpp Lexer.o Token.o Symbol.o Emitter.o
 	$(CC) -c $(FLAGS) $< 
 
-test.out: src/main.cpp Token.o Lexer.o Parser.o Symbol.o
+test.out: src/main.cpp Token.o Lexer.o Parser.o Symbol.o Emitter.o
 	$(CC) $(FLAGS) $^ -o $@
 	./$@ $(EXAMPLE)
+	cat out.c
 
 test: test.out
 	./$^ $(EXAMPLE)
+	cat out.c
 
 clean:
 	rm -f test.out *.o

+ 36 - 0
src/Emitter.cpp

@@ -0,0 +1,36 @@
+#include "Emitter.hpp"
+
+Emitter::Emitter(std::string path) : fullpath(path), header(""), code("") {}
+
+void Emitter::emit(std::string code)
+{
+  this->code += code;
+}
+
+void Emitter::emitLine(std::string code)
+{
+  this->code += code + '\n';
+}
+
+void Emitter::headerLine(std::string code)
+{
+  this->header += code + '\n';
+  // std::cout << code << std::endl;
+  // std::cout << this->header;
+}
+
+void Emitter::writeFile()
+{
+  std::ofstream outputFile(this->fullpath);
+  if (outputFile.is_open())
+  {
+    // std::cout << this->header + this->code << std::endl;
+    outputFile << this->header + this->code;
+    outputFile.close();
+  }
+  else
+  {
+    // Handle error
+    std::cerr << "Failed to open file: " << this->fullpath << std::endl;
+  }
+}

+ 16 - 0
src/Emitter.hpp

@@ -0,0 +1,16 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+
+class Emitter{
+  std::string fullpath;
+  std::string header;
+  std::string code;
+
+  public:
+  Emitter(std::string path);
+  void emit(std::string code);
+  void emitLine(std::string code);
+  void headerLine(std::string code);
+  void writeFile();
+};

+ 55 - 28
src/Parser.cpp

@@ -1,6 +1,6 @@
 #include "Parser.hpp"
 
-Parser::Parser(Lexer lexer) : lexer(lexer), curToken(Token()), peekToken(Token()), symbols({})
+Parser::Parser(Lexer lexer, Emitter *emitter) : lexer(lexer), curToken(Token()), peekToken(Token()), symbols({}), emitter(emitter)
 {
   nextToken();
   nextToken();
@@ -46,7 +46,9 @@ bool Parser::isComparisonOperator()
 
 void Parser::program()
 {
-  std::cout << "PROGRAM" << std::endl;
+  // std::cout << "PROGRAM" << std::endl;
+  this->emitter->headerLine("#include <stdio.h>");
+  this->emitter->headerLine("int main(void){");
   while (checkToken(TokenType::NEWLINE))
   {
     nextToken();
@@ -56,22 +58,27 @@ void Parser::program()
     statement();
   }
 
-  for (const Symbol& sym : this->symbols) {
-    if (sym.sym_kind() == SymbolKind::LABEL_GOTOED){
+  for (const Symbol &sym : this->symbols)
+  {
+    if (sym.sym_kind() == SymbolKind::LABEL_GOTOED)
+    {
       Symbol label(sym.str(), SymbolKind::LABEL_DECLARATION);
-      if (this->symbols.find(label) == this->symbols.end()){
-        abort ("GOTO to an undeclared label "+sym.str());
+      if (this->symbols.find(label) == this->symbols.end())
+      {
+        abort("GOTO to an undeclared label " + sym.str());
       }
     }
   }
 
-  Symbol label("TOTO", SymbolKind::LABEL_DECLARATION);
-  this->symbols.insert(label);
-  this->symbols.insert(label);
-  this->symbols.insert(label);
-  std::cout << "*** SYMB TABLE ***" << std::endl;
-  for (const Symbol& sym : this->symbols) {
-        std::cout << sym.str() << "-" << sym.sym_kind() << std::endl;
+  this->emitter->emitLine("return 0;");
+  this->emitter->emitLine("}");
+
+  for (const Symbol &sym : this->symbols)
+  {
+    if (sym.sym_kind() == SymbolKind::VARIABLE)
+    {
+      this->emitter->headerLine("float " + sym.str() + ";");
+    }
   }
 }
 
@@ -80,53 +87,63 @@ void Parser::statement()
   // "PRINT" (expression | string)
   if (checkToken(TokenType::PRINT))
   {
-    std::cout << "STATEMENT-PRINT" << std::endl;
+    // std::cout << "STATEMENT-PRINT" << std::endl;
     nextToken();
 
     if (checkToken(TokenType::STRING))
     {
+      this->emitter->emitLine("printf(\"" + this->curToken.get_text() + "\\n\")");
+      ;
       nextToken();
     }
     else
     {
+      this->emitter->emit("printf(\"\%.2f\\n\", (float)(");
       expression();
+      this->emitter->emitLine("));");
     }
   }
 
   // "IF" comparison "THEN" nl {statement} "ENDIF"
   else if (checkToken(TokenType::IF))
   {
-    std::cout << "STATEMENT-IF" << std::endl;
+    // std::cout << "STATEMENT-IF" << std::endl;
     nextToken();
+    this->emitter->emit("if(");
     comparison();
     match(TokenType::THEN);
     nl();
+    this->emitter->emitLine("){");
     while (!checkToken(TokenType::ENDIF))
     {
       statement();
     }
     match(TokenType::ENDIF);
+    this->emitter->emitLine("}");
   }
 
   // "WHILE" comparison "REPEAT" nl {statement nl} "ENDWHILE"
   else if (checkToken(TokenType::WHILE))
   {
-    std::cout << "STATEMENT-WHILE" << std::endl;
+    // std::cout << "STATEMENT-WHILE" << std::endl;
     nextToken();
+    this->emitter->emit("while(");
     comparison();
     match(TokenType::REPEAT);
     nl();
+    this->emitter->emitLine("){");
     while (!checkToken(TokenType::ENDWHILE))
     {
       statement();
     }
     match(TokenType::ENDWHILE);
+    this->emitter->emitLine("}");
   }
 
   // "LABEL" ident
   else if (checkToken(TokenType::LABEL))
   {
-    std::cout << "STATEMENT-LABEL" << std::endl;
+    // std::cout << "STATEMENT-LABEL" << std::endl;
     nextToken();
     ident(SymbolKind::LABEL_DECLARATION);
   }
@@ -134,25 +151,32 @@ void Parser::statement()
   // "GOTO" ident
   else if (checkToken(TokenType::GOTO))
   {
-    std::cout << "STATEMENT-GOTO" << std::endl;
+    // std::cout << "STATEMENT-GOTO" << std::endl;
     nextToken();
     ident(SymbolKind::LABEL_GOTOED);
   }
   // "LET" ident "=" expression
   else if (checkToken(TokenType::LET))
   {
-    std::cout << "STATEMENT-ASSIGN" << std::endl;
+    // std::cout << "STATEMENT-ASSIGN" << std::endl;
     nextToken();
     ident(SymbolKind::VARIABLE);
     match(TokenType::EQ);
+    this->emitter->emit(" = ");
     expression();
   }
   // "INPUT" ident
   else if (checkToken(TokenType::INPUT))
   {
-    std::cout << "STATEMENT-INPUT" << std::endl;
+    // std::cout << "STATEMENT-INPUT" << std::endl;
     nextToken();
+    this->emitter->emit("if (0 == scanf(\"\%f\", &");
+    const std::string identext = this->curToken.get_text();
     ident(SymbolKind::VARIABLE);
+    this->emitter->emitLine(")){");
+    this->emitter->emitLine(identext + " = 0;");
+    this->emitter->emitLine("}");
+    this->emitter->emitLine("scanf(\"\%*s\");\n}");
   }
 
   else
@@ -165,7 +189,7 @@ void Parser::statement()
 
 void Parser::comparison()
 {
-  std::cout << "COMPARISON" << std::endl;
+  // std::cout << "COMPARISON" << std::endl;
   expression();
   if (isComparisonOperator())
   {
@@ -186,7 +210,7 @@ void Parser::comparison()
 
 void Parser::term()
 {
-  std::cout << "TERM" << std::endl;
+  // std::cout << "TERM" << std::endl;
   unary();
   while (checkToken(TokenType::ASTERISK) || checkToken(TokenType::SLASH))
   {
@@ -197,7 +221,7 @@ void Parser::term()
 
 void Parser::unary()
 {
-  std::cout << "UNARY" << std::endl;
+  // std::cout << "UNARY" << std::endl;
   if (checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS))
   {
     nextToken();
@@ -207,7 +231,7 @@ void Parser::unary()
 
 void Parser::primary()
 {
-  std::cout << "PRIMARY" << " (" << (this->curToken).get_text() << ")" << std::endl;
+  // std::cout << "PRIMARY" << " (" << (this->curToken).get_text() << ")" << std::endl;
   if (checkToken(TokenType::NUMBER))
   {
     nextToken();
@@ -230,7 +254,7 @@ void Parser::primary()
 
 void Parser::expression()
 {
-  std::cout << "EXPRESSION" << std::endl;
+  // std::cout << "EXPRESSION" << std::endl;
   term();
   while (checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS))
   {
@@ -241,7 +265,7 @@ void Parser::expression()
 
 void Parser::ident(SymbolKind k)
 {
-  std::cout << "IDENT" << std::endl;
+  // std::cout << "IDENT" << std::endl;
   const std::string identText = this->curToken.get_text();
   match(TokenType::IDENT);
   Symbol curSymb(identText, k);
@@ -251,13 +275,16 @@ void Parser::ident(SymbolKind k)
     if (this->symbols.find(curSymb) != this->symbols.end())
       abort("Label already exists " + identText);
     this->symbols.insert(curSymb);
+    this->emitter->emit(identText + ": ");
     break;
   case LABEL_GOTOED:
     this->symbols.insert(curSymb);
+    this->emitter->emitLine("goto " + identText + ";");
     break;
   case VARIABLE:
-    std::cout << identText << std::endl;
+    // std::cout << identText << std::endl;
     this->symbols.insert(curSymb);
+    this->emitter->emit(identText);
     break;
   default:
     break;
@@ -266,7 +293,7 @@ void Parser::ident(SymbolKind k)
 
 void Parser::nl()
 {
-  std::cout << "NEWLINE" << std::endl;
+  // std::cout << "NEWLINE" << std::endl;
   match(TokenType::NEWLINE);
   while (checkToken(TokenType::NEWLINE))
   {

+ 5 - 2
src/Parser.hpp

@@ -1,16 +1,19 @@
+#include <set>
 #include "Lexer.hpp"
 #include "Symbol.hpp"
-#include <set>
+#include "Emitter.hpp"
+
 
 class Parser {
   Lexer lexer;
   Token curToken;
   Token peekToken;
   std::set<Symbol> symbols;
+  Emitter* emitter;
 
 
   public:
-  Parser(Lexer lexer);
+  Parser(Lexer lexer, Emitter *emitter);
   bool checkToken(TokenType kind);
   bool checkPeek(TokenType kind);
   void match(TokenType kind);

+ 4 - 1
src/main.cpp

@@ -22,7 +22,10 @@ int main(int argc, char* argv[])
   std::string source = ss.str();
 
   Lexer mylexer(source);
-  Parser myparser(mylexer);
+  Emitter* emitter = new Emitter("out.c");
+  Parser myparser(mylexer, emitter);
   myparser.program();
+  emitter->writeFile();
+  delete emitter;
   return 0;
 }