From b12c01732860f9727626829e0b25a273de5fe5c7 Mon Sep 17 00:00:00 2001 From: geno Date: Tue, 25 Jun 2024 16:04:07 +0200 Subject: [PATCH] check semantic of defined and undefined variables implemented do not check for built-in function works on the example --- src/Main.java | 2 +- src/ast/nodes/AtomNode.java | 31 ++++--- src/ast/nodes/ExprNode.java | 121 +++++++++++++++++++++----- src/ast/nodes/RootNode.java | 8 +- src/ast/types/VoidType.java | 6 ++ src/semanticanalysis/SymbolTable.java | 17 ++-- 6 files changed, 140 insertions(+), 45 deletions(-) diff --git a/src/Main.java b/src/Main.java index 3987bad..bfc21e3 100644 --- a/src/Main.java +++ b/src/Main.java @@ -60,7 +60,7 @@ public static void main(String[] args) { Node ast = visitor.visit(tree); ArrayList errors = ast.checkSemantics(ST, 0); if (errors.size() > 0) { - System.out.println("You had: " + errors.size() + " errors:"); + System.out.println("You had " + errors.size() + " errors:"); for (SemanticError e : errors) { System.out.println("\t" + e); } diff --git a/src/ast/nodes/AtomNode.java b/src/ast/nodes/AtomNode.java index 7dc38fb..4c9a807 100644 --- a/src/ast/nodes/AtomNode.java +++ b/src/ast/nodes/AtomNode.java @@ -1,15 +1,17 @@ package ast.nodes; +import ast.types.*; import java.util.ArrayList; - +import java.util.regex.Matcher; +import java.util.regex.Pattern; import semanticanalysis.SemanticError; import semanticanalysis.SymbolTable; -import ast.types.*; /** * Node for the `atom` statement of the grammar. */ public class AtomNode implements Node { + protected String val; public AtomNode(String val) { @@ -23,25 +25,28 @@ public String getId() { @Override public ArrayList checkSemantics(SymbolTable ST, int _nesting) { var errors = new ArrayList(); - System.out.println(getId() + " " + _nesting + " " + ST.nslookup(getId())); - if (!(this.typeCheck() instanceof IntType) && !ST.top_lookup(this.getId())) { - System.out.println(!(this.typeCheck() instanceof IntType) + " " + !ST.top_lookup(this.getId())); + // System.out.println("[ATOM] id: " + getId() + " ns: " + _nesting + " top_lookup" + ST.top_lookup(this.getId())); + if ((this.typeCheck() instanceof AtomType) && !ST.top_lookup(this.getId())) { + // System.out.println(!(this.typeCheck() instanceof IntType) + " " + !ST.top_lookup(this.getId())); errors.add(new SemanticError("Undefined name `" + this.getId() + "`")); } return errors; } - // FIXME: this type for atom + // ENHANCE: return more specific types @Override public Type typeCheck() { - try { - Integer.parseInt(this.val); - System.out.println(this.val + " is int"); - return new IntType(); - } catch (NumberFormatException e) { - System.out.println(this.val + " is atom"); - return new AtomType(); + // this regex should match every possible atom name written in this format: CHAR (CHAR | DIGIT)* + Pattern pattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9]*$", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(this.val); + boolean matchFound = matcher.find(); + if (matchFound) { + // System.out.println("Match found for " + this.val); + return new AtomType(); // could be a variable or a fuction + } else { + // System.out.println("Match not found for " + this.val); + return new VoidType(); // could be any type of data } } diff --git a/src/ast/nodes/ExprNode.java b/src/ast/nodes/ExprNode.java index 39f397e..13b6619 100644 --- a/src/ast/nodes/ExprNode.java +++ b/src/ast/nodes/ExprNode.java @@ -1,23 +1,96 @@ package ast.nodes; +import ast.types.*; import java.util.ArrayList; - +import java.util.Arrays; import semanticanalysis.SemanticError; import semanticanalysis.SymbolTable; -import ast.types.*; /** * Node for the `expr` statement of the grammar. */ public class ExprNode implements Node { - private Node atom; + + private AtomNode atom; private Node compOp; private String op; private ArrayList exprs; private ArrayList trailers; + private static final String[] bif = {"abs", + "aiter", + "all", + "anext", + "any", + "ascii", + "bin", + "bool", + "breakpoint", + "bytearray", + "bytes", + "callable", + "chr", + "classmethod", + "compile", + "complex", + "delattr", + "dict", + "dir", + "divmod", + "enumerate", + "eval", + "exec", + "filter", + "float", + "format", + "frozenset", + "getattr", + "globals", + "hasattr", + "hash", + "help", + "hex", + "id", + "input", + "int", + "isinstance", + "issubclass", + "iter", + "len", + "list", + "locals", + "map", + "max", + "memoryview", + "min", + "next", + "object", + "oct", + "open", + "ord", + "pow", + "print", + "property", + "range", + "repr", + "reversed", + "round", + "set", + "setattr", + "slice", + "sorted", + "staticmethod", + "str", + "sum", + "super", + "tuple", + "type", + "vars", + "zip", + "__import__"}; + public ExprNode(Node atom, Node compOp, ArrayList exprs, String op, ArrayList trailers) { - this.atom = atom; + this.atom = (AtomNode) atom; this.compOp = compOp; this.exprs = exprs; this.op = op; @@ -31,20 +104,28 @@ public String getId() { @Override public ArrayList checkSemantics(SymbolTable ST, int _nesting) { ArrayList errors = new ArrayList(); - if (atom != null) { - errors.addAll(atom.checkSemantics(ST, _nesting)); - } - - if (compOp != null) { - errors.addAll(compOp.checkSemantics(ST, _nesting)); - } - - for (var expr : exprs) { - errors.addAll(expr.checkSemantics(ST, _nesting)); - } - - for (var trailer : trailers) { - errors.addAll(trailer.checkSemantics(ST, _nesting)); + if (atom != null && !trailers.isEmpty()) { + // function call + if (!Arrays.asList(bif).contains(atom.getId())) { + errors.addAll(atom.checkSemantics(ST, _nesting)); + } + } else { + // butto tutto quello che c'era prima nell'else così non rischio di perdere niente di utile + if (atom != null) { + errors.addAll(atom.checkSemantics(ST, _nesting)); + } + + if (compOp != null) { + errors.addAll(compOp.checkSemantics(ST, _nesting)); + } + + for (var expr : exprs) { + errors.addAll(expr.checkSemantics(ST, _nesting)); + } + + for (var trailer : trailers) { + errors.addAll(trailer.checkSemantics(ST, _nesting)); + } } return errors; @@ -81,11 +162,11 @@ public String toPrint(String prefix) { for (var expr : exprs) { str += expr.toPrint(prefix); - } + } for (var trailer : trailers) { str += trailer.toPrint(prefix); - } + } if (op != null) { str += prefix + "Op(" + op + ")\n"; diff --git a/src/ast/nodes/RootNode.java b/src/ast/nodes/RootNode.java index 4b7e579..45d20db 100644 --- a/src/ast/nodes/RootNode.java +++ b/src/ast/nodes/RootNode.java @@ -1,15 +1,15 @@ package ast.nodes; +import ast.types.*; import java.util.ArrayList; import java.util.HashMap; - import semanticanalysis.*; -import ast.types.*; /** * Node for the `root` statement of the grammar. */ public class RootNode implements Node { + // stms and compundStmts are protected because they are reused for a // BlockNode protected ArrayList stmts; @@ -28,11 +28,11 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { ST.add(HM); - for (Node stmt : compoundStmts) { + for (Node stmt : stmts) { errors.addAll(stmt.checkSemantics(ST, _nesting)); } - for (Node stmt : stmts) { + for (Node stmt : compoundStmts) { errors.addAll(stmt.checkSemantics(ST, _nesting)); } diff --git a/src/ast/types/VoidType.java b/src/ast/types/VoidType.java index d15933f..8e3f9b2 100644 --- a/src/ast/types/VoidType.java +++ b/src/ast/types/VoidType.java @@ -4,7 +4,13 @@ * A void type. Voids return nothing. */ public class VoidType extends Type { + public String toPrint(String prefix) { return prefix + "Void\n"; } + + @Override + public String toString() { + return "Void"; + } } diff --git a/src/semanticanalysis/SymbolTable.java b/src/semanticanalysis/SymbolTable.java index 8193d5e..617b48a 100644 --- a/src/semanticanalysis/SymbolTable.java +++ b/src/semanticanalysis/SymbolTable.java @@ -126,15 +126,18 @@ public void insert(String id, Type type, int _nesting, String _label) { // We always increment the offset by 1 otherwise we need ad-hoc bytecode // operations // FIXME: wtf is that? - if (type.getClass().equals((new BoolType()).getClass())) { - offs = offs + 1; - } else if (type.getClass().equals((new IntType()).getClass())) { - offs = offs + 1; - } else { - offs = offs + 1; - } + // if (type.getClass().equals((new BoolType()).getClass())) { + // offs = offs + 1; + // } else if (type.getClass().equals((new IntType()).getClass())) { + // offs = offs + 1; + // } else { + // offs = offs + 1; + // } + offs = offs + 1; this.offset.add(offs); + + // System.out.println("Insert " + id + " of type " + type.toString() + " with nesting " + String.valueOf(_nesting)); } /**