AbderFaiz преди 5 месеца
родител
ревизия
b0bca51b6b
променени са 6 файла, в които са добавени 150 реда и са изтрити 38 реда
  1. 8 2
      Makefile
  2. 3 1
      examples/factorial
  3. 101 34
      src/Parser.cpp
  4. 5 1
      src/Parser.hpp
  5. 13 0
      src/Symbol.cpp
  6. 20 0
      src/Symbol.hpp

+ 8 - 2
Makefile

@@ -7,15 +7,21 @@ all: test.out
 Token.o : src/Token.cpp src/Token.hpp
 	$(CC) -c $(FLAGS) $< 
 
+Symbol.o : src/Symbol.cpp src/Symbol.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
+Parser.o : src/Parser.cpp src/Parser.hpp Lexer.o Token.o Symbol.o
 	$(CC) -c $(FLAGS) $< 
 
-test.out: src/main.cpp Token.o Lexer.o Parser.o
+test.out: src/main.cpp Token.o Lexer.o Parser.o Symbol.o
 	$(CC) $(FLAGS) $^ -o $@
 	./$@ $(EXAMPLE)
 
+test: test.out
+	./$^ $(EXAMPLE)
+
 clean:
 	rm -f test.out *.o

+ 3 - 1
examples/factorial

@@ -1,12 +1,14 @@
+LABEL START
 PRINT "Enter a number to compute its factorial:"
 INPUT n
 PRINT ""
 
 LET result = 1
+
 WHILE n > 1 REPEAT
     LET result = result * n
     LET n = n - 1
 ENDWHILE
-
 PRINT "The factorial is:"
 PRINT result
+GOTO START

+ 101 - 34
src/Parser.cpp

@@ -1,6 +1,6 @@
 #include "Parser.hpp"
 
-Parser::Parser(Lexer lexer) : lexer(lexer), curToken(Token()), peekToken(Token())
+Parser::Parser(Lexer lexer) : lexer(lexer), curToken(Token()), peekToken(Token()), symbols({})
 {
   nextToken();
   nextToken();
@@ -34,34 +34,53 @@ void Parser::abort(std::string message)
   exit(1);
 }
 
-bool Parser::isComparisonOperator(){
-  return (checkToken(TokenType::GT)   || 
+bool Parser::isComparisonOperator()
+{
+  return (checkToken(TokenType::GT) ||
           checkToken(TokenType::GTEQ) ||
           checkToken(TokenType::EQEQ) ||
-          checkToken(TokenType::NOTEQ)||
+          checkToken(TokenType::NOTEQ) ||
           checkToken(TokenType::LTEQ) ||
-          checkToken(TokenType::LT)
-        );
+          checkToken(TokenType::LT));
 }
 
 void Parser::program()
 {
   std::cout << "PROGRAM" << std::endl;
-  while (checkToken(TokenType::NEWLINE)){
+  while (checkToken(TokenType::NEWLINE))
+  {
     nextToken();
   }
   while (!checkToken(TokenType::END_OF_FILE))
   {
     statement();
   }
+
+  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());
+      }
+    }
+  }
+
+  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;
+  }
 }
 
 void Parser::statement()
 {
-  std::cout << "STATEMENT" << std::endl;
   // "PRINT" (expression | string)
   if (checkToken(TokenType::PRINT))
   {
+    std::cout << "STATEMENT-PRINT" << std::endl;
     nextToken();
 
     if (checkToken(TokenType::STRING))
@@ -77,6 +96,7 @@ void Parser::statement()
   // "IF" comparison "THEN" nl {statement} "ENDIF"
   else if (checkToken(TokenType::IF))
   {
+    std::cout << "STATEMENT-IF" << std::endl;
     nextToken();
     comparison();
     match(TokenType::THEN);
@@ -91,6 +111,7 @@ void Parser::statement()
   // "WHILE" comparison "REPEAT" nl {statement nl} "ENDWHILE"
   else if (checkToken(TokenType::WHILE))
   {
+    std::cout << "STATEMENT-WHILE" << std::endl;
     nextToken();
     comparison();
     match(TokenType::REPEAT);
@@ -103,31 +124,40 @@ void Parser::statement()
   }
 
   // "LABEL" ident
-  else if (checkToken(TokenType::LABEL)){
+  else if (checkToken(TokenType::LABEL))
+  {
+    std::cout << "STATEMENT-LABEL" << std::endl;
     nextToken();
-    ident();
+    ident(SymbolKind::LABEL_DECLARATION);
   }
 
   // "GOTO" ident
-  else if (checkToken(TokenType::GOTO)){
+  else if (checkToken(TokenType::GOTO))
+  {
+    std::cout << "STATEMENT-GOTO" << std::endl;
     nextToken();
-    ident();
+    ident(SymbolKind::LABEL_GOTOED);
   }
   // "LET" ident "=" expression
-  else if (checkToken(TokenType::LET)){
+  else if (checkToken(TokenType::LET))
+  {
+    std::cout << "STATEMENT-ASSIGN" << std::endl;
     nextToken();
-    ident();
+    ident(SymbolKind::VARIABLE);
     match(TokenType::EQ);
     expression();
   }
   // "INPUT" ident
-  else if (checkToken(TokenType::INPUT)){
+  else if (checkToken(TokenType::INPUT))
+  {
+    std::cout << "STATEMENT-INPUT" << std::endl;
     nextToken();
-    ident();
+    ident(SymbolKind::VARIABLE);
   }
 
-  else{
-    abort("Invalid statement at "+ (this->curToken).get_text() + "(" + token_name((this->curToken).get_kind()) + ")");
+  else
+  {
+    abort("Invalid statement at " + (this->curToken).get_text() + "(" + token_name((this->curToken).get_kind()) + ")");
   }
 
   nl();
@@ -137,47 +167,64 @@ void Parser::comparison()
 {
   std::cout << "COMPARISON" << std::endl;
   expression();
-  if (isComparisonOperator()){
+  if (isComparisonOperator())
+  {
     nextToken();
     expression();
   }
-  else {
-    abort("Expected comparison operator at: "+(this->curToken).get_text());
+  else
+  {
+    abort("Expected comparison operator at: " + (this->curToken).get_text());
   }
 
-  while (isComparisonOperator()){
+  while (isComparisonOperator())
+  {
     nextToken();
     expression();
   }
 }
 
-void Parser::term(){
+void Parser::term()
+{
   std::cout << "TERM" << std::endl;
   unary();
-  while(checkToken(TokenType::ASTERISK) || checkToken(TokenType::SLASH)){
+  while (checkToken(TokenType::ASTERISK) || checkToken(TokenType::SLASH))
+  {
     nextToken();
     unary();
   }
 }
 
-void Parser::unary(){
+void Parser::unary()
+{
   std::cout << "UNARY" << std::endl;
-  if(checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS)){
+  if (checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS))
+  {
     nextToken();
   }
   primary();
 }
 
-void Parser::primary(){
-  std::cout << "PRIMARY" << " (" << (this->curToken).get_text() << ")"<< std::endl;
-  if(checkToken(TokenType::NUMBER)){
+void Parser::primary()
+{
+  std::cout << "PRIMARY" << " (" << (this->curToken).get_text() << ")" << std::endl;
+  if (checkToken(TokenType::NUMBER))
+  {
     nextToken();
   }
-  else if(checkToken(TokenType::IDENT)){
+  else if (checkToken(TokenType::IDENT))
+  {
+    const std::string identext = this->curToken.get_text();
+    Symbol tmp(identext, SymbolKind::VARIABLE);
+    if (this->symbols.find(tmp) == this->symbols.end())
+    {
+      abort("Underclared variable " + this->curToken.get_text());
+    }
     nextToken();
   }
-  else{
-    abort("Unexpected token at "+ (this->curToken).get_text());
+  else
+  {
+    abort("Unexpected token at " + (this->curToken).get_text());
   }
 }
 
@@ -185,16 +232,36 @@ void Parser::expression()
 {
   std::cout << "EXPRESSION" << std::endl;
   term();
-  while(checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS)){
+  while (checkToken(TokenType::PLUS) || checkToken(TokenType::MINUS))
+  {
     nextToken();
     term();
   }
 }
 
-void Parser::ident()
+void Parser::ident(SymbolKind k)
 {
   std::cout << "IDENT" << std::endl;
+  const std::string identText = this->curToken.get_text();
   match(TokenType::IDENT);
+  Symbol curSymb(identText, k);
+  switch (k)
+  {
+  case LABEL_DECLARATION:
+    if (this->symbols.find(curSymb) != this->symbols.end())
+      abort("Label already exists " + identText);
+    this->symbols.insert(curSymb);
+    break;
+  case LABEL_GOTOED:
+    this->symbols.insert(curSymb);
+    break;
+  case VARIABLE:
+    std::cout << identText << std::endl;
+    this->symbols.insert(curSymb);
+    break;
+  default:
+    break;
+  }
 }
 
 void Parser::nl()

+ 5 - 1
src/Parser.hpp

@@ -1,9 +1,13 @@
 #include "Lexer.hpp"
+#include "Symbol.hpp"
+#include <set>
 
 class Parser {
   Lexer lexer;
   Token curToken;
   Token peekToken;
+  std::set<Symbol> symbols;
+
 
   public:
   Parser(Lexer lexer);
@@ -21,6 +25,6 @@ class Parser {
   void term();
   void unary();
   void primary();
-  void ident();
+  void ident(SymbolKind k);
   void nl();
 };

+ 13 - 0
src/Symbol.cpp

@@ -0,0 +1,13 @@
+#include "Symbol.hpp"
+
+Symbol::Symbol(const std::string id, SymbolKind k): txt(id), kind(k)
+{
+}
+
+std::string Symbol::str() const{
+  return this->txt;
+}
+
+SymbolKind Symbol::sym_kind() const{
+  return this->kind;
+}

+ 20 - 0
src/Symbol.hpp

@@ -0,0 +1,20 @@
+#include <iostream>
+#include <string>
+
+enum SymbolKind {
+  VARIABLE, LABEL_DECLARATION, LABEL_GOTOED
+};
+
+
+class Symbol{
+  std::string txt;
+  SymbolKind kind;
+
+  public:
+  Symbol(const std::string id, SymbolKind k);
+  std::string str() const;
+  SymbolKind sym_kind() const;
+  bool operator<(const Symbol& other) const{
+      return std::tie(this->txt,this->kind) < std::tie(other.txt, other.kind);
+  }
+};