diff --git a/sources/zweic/Analyzer.scala b/sources/zweic/Analyzer.scala new file mode 100755 index 0000000..8fa49bf --- /dev/null +++ b/sources/zweic/Analyzer.scala @@ -0,0 +1,112 @@ +/* zweic -- a compiler for Zwei + * + * Stephane Micheloud & LAMP + * + * $Id$ + */ + +package zweic; + +/** + * This class implements the semantic analyzer of zweic. + */ +class Analyzer { + + import Operators._; + import scala.collection.immutable.{Map, ListMap}; + + // Global scope of classes + type ClassScope = Map[String, ClassSymbol]; + var classScope: ClassScope = ListMap.Empty; + + // For local scopes of variables + type VarScope = Map[String, VarSymbol]; + val emptyVarScope: VarScope = ListMap.Empty; + + // Analyze a program + def analyzeProgram(tree: Program): Unit = + tree match { + + case Program(classes, main) => + classes.foreach(analyzeClass); + analyzeExpr(emptyVarScope, main); + () + } + + // Analyze a class + private def analyzeClass(tree: ClassDef): Unit = + // ... � compl�ter ... + + // Analyze a member + private def analyzeMember(ownerClass: ClassSymbol, tree: Member): Unit = + // ... � compl�ter ... + + // Analyze a statement + private def analyzeStat(varScope: VarScope, tree: Stat): VarScope = + tree match { + + case While(cond, stats) => + checkIntType(cond.pos, analyzeExpr(varScope, cond)); + stats.foldLeft(varScope)(analyzeStat); + varScope + // ... � compl�ter ... + } + + // Analyze a type + private def analyzeType(tree: TypeTree): Type = + tree match { + case IntType() => IIntType + case NullType() => INullType + case ClassType(name) => + classScope.get(name.name) match { + case Some(c) => + name.sym = c; + IClassType(c) + case None => + Report.error(tree.pos, "Class " + name + " is unknown"); + IBadType + } + } + + // Analyze an expression + private def analyzeExpr(varScope: VarScope, tree: Expr): Type = + tree match { + // ... � compl�ter ... + case NullLit() => + INullType + + case IntLit(_) => + IIntType + // ... � compl�ter ... + } + + /** + * Generates an error if the expected type is not equal + * to the found type. + */ + private def checkSametype(pos: Int, found: Type, expected: Type): Unit = + if (!found.isSametype(expected)) + error(pos, "Type mismatch", found, expected); + + /** + * Generates an error if the found type is not equal to IIntType. + */ + private def checkIntType(pos: Int, found: Type): Unit = + checkSametype(pos, found, IIntType); + + /** + * Generates an error if the expected type is not a super type + * of the found type. + */ + private def checkSubtype(pos: Int, header: String, found: Type, expected: Type) = + if (!found.isSubtype(expected)) + error(pos, header, found, expected); + + /** + * Generates an error message for unexpected types. + */ + private def error(pos: Int, header: String, found: Type, expected: Type) = + Report.error(pos, header + "\nexpected type: " + expected + "\n" + + "actual type : " + found); + +} diff --git a/sources/zweic/AnalyzerTest.scala b/sources/zweic/AnalyzerTest.scala new file mode 100755 index 0000000..2569579 --- /dev/null +++ b/sources/zweic/AnalyzerTest.scala @@ -0,0 +1,41 @@ +/* zweic -- a compiler for Zwei + * + * Stephane Micheloud & LAMP + * + * $Id$ + */ + +package zweic; + + +/** A small test class for the semantic analyzer of zweic; it reads + * in a file and prints out the abstract syntax tree. If the program + * is erroneous, the compiler will print a corresponding error message + * instead. + * + * usage: scala zweic.AnalyzerTest + */ +object AnalyzerTest { + import java.io.{FileInputStream, IOException}; + + def main(args: Array[String]): Unit = { + if (args.length != 1) { + Console.println("usage: scala zweic.AnalyzerTest "); + System.exit(1) + } + try { + val in = new FileInputStream(args(0)); + val tree = new Parser(in).parse; + in.close(); + if (Report.errors > 0) + System.err.println(Report.errors + " errors found."); + else + new Analyzer().analyzeProgram(tree); + System.exit(if (Report.errors > 0) 1 else 0); + } + catch { + case e: IOException => Report.fail(e.getMessage()) + } + } + +} diff --git a/sources/zweic/ScannerTest.scala b/sources/zweic/ScannerTest.scala index 0a73087..fc89b66 100755 --- a/sources/zweic/ScannerTest.scala +++ b/sources/zweic/ScannerTest.scala @@ -27,9 +27,9 @@ val scanner = new Scanner(in); while (scanner.token != Tokens.EOF) { Console.println(scanner.representation); - scanner.nextToken; + scanner.nextToken } - in.close + in.close() } catch { case e: IOException => Report.fail(e.getMessage()); diff --git a/sources/zweic/Type.scala b/sources/zweic/Type.scala new file mode 100755 index 0000000..dfaea15 --- /dev/null +++ b/sources/zweic/Type.scala @@ -0,0 +1,45 @@ +/* zweic -- a compiler for zwei + * + * Stephane Micheloud & LAMP + * + * $Id$ + */ + +package zweic; + +// Internal type +abstract class Type { + + override def toString(): String = this match { + // ... � compl�ter ... + case IBadType => "" + } + + def isSubtype(that: Type): Boolean = Pair(this, that) match { + // ... � compl�ter ... + case _ => false + } + + def isSametype(that: Type): Boolean = Pair(this, that) match { + // ... � compl�ter ... + case _ => false + } + + def lub(that: Type): Option[Type] = Pair(this, that) match { + // ... � compl�ter ... + case _ => None + } + +} + +// Class type +case class IClassType(c: ClassSymbol) extends Type; + +// Integer type +case object IIntType extends Type; + +// Null type +case object INullType extends Type; + +// Bad type +case object IBadType extends Type;