Nicolas Winkler 7 éve
szülő
commit
fde8c4287d
7 módosított fájl, 68 hozzáadás és 18 törlés
  1. 1 0
      src/Ast.h
  2. 19 1
      src/AstVisitor.cpp
  3. 4 0
      src/AstVisitor.h
  4. 16 3
      src/Semantic.cpp
  5. 4 2
      src/Semantic.h
  6. 24 3
      src/main.cpp
  7. 0 9
      src/parser.y

+ 1 - 0
src/Ast.h

@@ -83,6 +83,7 @@ namespace qlow
  */
 struct qlow::CodePosition
 {
+    const char* filename;
     int first_line;
     int last_line;
     int first_column;

+ 19 - 1
src/AstVisitor.cpp

@@ -10,7 +10,7 @@ sem::Class* StructureVisitor::getType(const std::string& type, const sem::Symbol
     if (t != classes.end())
         return t->second.get();
     else
-        throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE, type);
+        return nullptr;
 }
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, const sem::SymbolTable<sem::Class>& classes)
@@ -32,6 +32,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclarati
     auto f = std::make_unique<sem::Field>();
     f->name = ast.name;
     f->type = getType(ast.type, classes);
+    if (f->type == nullptr) {
+        throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
+            ast.type,
+            ast.pos
+        );
+    }
     return f;
 }
 
@@ -41,6 +47,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
     auto m = std::make_unique<sem::Method>();
     m->name = ast.name;
     m->returnType = getType(ast.type, classes);
+    if (m->returnType == nullptr) {
+        throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
+            ast.type,
+            ast.pos
+        );
+    }
     return m;
 }
 
@@ -50,6 +62,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
     auto v = std::make_unique<sem::Variable>();
     v->name = ast.name;
     v->type = getType(ast.type, classes);
+    if (v->type == nullptr) {
+        throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
+            ast.type,
+            ast.pos
+        );
+    }
     return v;
 }
 

+ 4 - 0
src/AstVisitor.h

@@ -74,6 +74,10 @@ class qlow::StructureVisitor :
 public:
     using ReturnType = std::unique_ptr<sem::SemanticObject>;
     
+    /*!
+     * 
+     * \returns <code>nullptr</code> if type is not found.
+     */
     sem::Class* getType(const std::string& type, const sem::SymbolTable<sem::Class>& classes);
 
     ReturnType visit(ast::Class& ast, const sem::SymbolTable<sem::Class>& classes) override;

+ 16 - 3
src/Semantic.cpp

@@ -47,14 +47,14 @@ SymbolTable<qlow::sem::Class>
             
             if (auto* field = dynamic_cast<qlow::ast::FieldDeclaration*> (feature.get()); field) {
                 if (semClass->fields.find(field->name) != semClass->fields.end()) // throw, if field already exists
-                    throw SemanticException(SemanticException::DUPLICATE_FIELD_DECLARATION, field->name);
+                    throw SemanticException(SemanticException::DUPLICATE_FIELD_DECLARATION, field->name, field->pos);
                 
                 // otherwise add to the fields list
                 semClass->fields[field->name] = unique_dynamic_cast<Field>(av.visit(*field, semClasses));
             }
             else if (auto* method = dynamic_cast<qlow::ast::MethodDefinition*> (feature.get()); method) {
                 if (semClass->methods.find(method->name) != semClass->methods.end()) // throw, if method already exists
-                    throw SemanticException(SemanticException::DUPLICATE_METHOD_DEFINITION, method->name);
+                    throw SemanticException(SemanticException::DUPLICATE_METHOD_DEFINITION, method->name, method->pos);
                 
                 // otherwise add to the methods list
                 semClass->methods[method->name] = unique_dynamic_cast<Method>(av.visit(*method, semClasses));
@@ -88,10 +88,19 @@ std::string SemanticObject::toString(void) const
 std::string Class::toString(void) const
 {
     std::string val = "Class[";
+    
+    // add fields
     for (auto& field : fields)
         val += field.second->toString() + ", ";
     if (!fields.empty())
         val = val.substr(0, val.length() - 2);
+    
+    // add methods
+    for (auto& method : methods)
+        val += method.second->toString() + ", ";
+    if (!methods.empty())
+        val = val.substr(0, val.length() - 2);
+    
     val += " (";
     val += std::to_string(this->astNode->pos.first_line) + ", ";
     val += std::to_string(this->astNode->pos.first_column);
@@ -119,7 +128,11 @@ std::string SemanticException::getMessage(void) const
         {UNKNOWN_TYPE, "unknown type"},
     };
     
-    return error[errorCode] + ": " + message;
+    std::string pos = std::to_string(where.first_line) + ":" +
+        std::to_string(where.first_column);
+    
+    return pos + ": " + error[errorCode] + ": " + message;
 }
 
 
+

+ 4 - 2
src/Semantic.h

@@ -89,6 +89,7 @@ struct qlow::sem::Variable : public SemanticObject
 class qlow::sem::SemanticException
 {
     std::string message;
+    qlow::CodePosition where;
 public:
     enum ErrorCode
     {
@@ -101,8 +102,9 @@ public:
     
     ErrorCode errorCode;
 public:
-    inline SemanticException(ErrorCode ec, const std::string& arg) :
-        message{ arg }, errorCode{ ec }
+    inline SemanticException(ErrorCode ec, const std::string& arg, const
+        qlow::CodePosition& where) :
+        message{ arg }, where{ where }, errorCode{ ec }
     {}
 
     std::string getMessage(void) const;

+ 24 - 3
src/main.cpp

@@ -1,4 +1,7 @@
 #include <iostream>
+
+#include <unistd.h>
+
 #include "Ast.h"
 #include "Semantic.h"
 
@@ -6,13 +9,28 @@ extern std::unique_ptr<std::vector<std::unique_ptr<qlow::ast::Class>>> parsedCla
 extern FILE* qlow_parser_in;
 extern int qlow_parser_parse(void);
 
+
 int main(int argc, char** argv)
 {
+    int c;
+    while ((c = getopt(argc, argv, "c:")) != -1) {
+        switch (c) {
+            case 'c':
+                printf("c: %s", optarg);
+            break;
+            default:
+                printf("ay: %c\n", c);
+        }
+    }
+    
+    const char* filename = argv[optind];
+    
     try {
-        qlow_parser_in = stdin;
+        ::qlow_parser_in = stdin;
         
-        if (argc > 1)
-            qlow_parser_in = ::fopen(argv[1], "r");
+        ::qlow_parser_in = fopen(filename, "r");
+        if (!::qlow_parser_in)
+            throw (std::string("File not found: ") + filename).c_str();
         
         ::qlow_parser_parse();
         std::cout << parsedClasses->size() << std::endl;
@@ -36,6 +54,9 @@ int main(int argc, char** argv)
     catch (...)
     {
     }
+    
+    if (::qlow_parser_in != stdin)
+        fclose(::qlow_parser_in);
 }
 
 

+ 0 - 9
src/parser.y

@@ -42,15 +42,6 @@ int qlow_parser_error(const char*)
 #define QLOW_PARSER_LTYPE_IS_DECLARED
 typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 
-/*
-typedef struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-} YYLTYPE;
-*/
 
 using ClassList = std::vector<std::unique_ptr<qlow::ast::Class>>;
 std::unique_ptr<ClassList> parsedClasses;