pass all tests
This commit is contained in:
@@ -42,6 +42,9 @@ OPTION: compX86, intStack, intValue (default)""")
|
||||
args(0)
|
||||
}
|
||||
|
||||
// val source = Source.fromFile("examples/unexpected_character.scala")
|
||||
// val src = try source.getLines mkString "\n" finally source.close()
|
||||
|
||||
println("============ SRC CODE ============")
|
||||
println(src)
|
||||
println("==================================\n")
|
||||
@@ -51,7 +54,7 @@ OPTION: compX86, intStack, intValue (default)""")
|
||||
|
||||
// Parser to test!
|
||||
// TODO: Change this as you finish parsers
|
||||
val parser = new ArithParser(scanner)
|
||||
val parser = new LoopParser(scanner)
|
||||
val ast = parser.parseCode
|
||||
|
||||
println("============= AST ================")
|
||||
|
||||
@@ -88,11 +88,11 @@ class Scanner(in: Reader[Char]) extends Reader[Tokens.Token] with Reporter {
|
||||
|
||||
// List of delimiters
|
||||
// TODO: Update this as delimiters are added to our language
|
||||
val isDelim = Set('(',')')
|
||||
val isDelim = Set('(', ')', ';', '{', '}')
|
||||
|
||||
// List of keywords
|
||||
// TODO: Update this as keywords are added to our language
|
||||
val isKeyword = Set[String]("val", "var")
|
||||
val isKeyword = Set[String]("val", "var", "if", "else", "while")
|
||||
|
||||
/*
|
||||
* Extract a name from the stream
|
||||
@@ -429,9 +429,12 @@ class ArithParser(in: Scanner) extends Parser(in) {
|
||||
def parseExpression(min: Int): Exp = {
|
||||
var res = parseUAtom
|
||||
// TODO: complete DONE?
|
||||
if (in.hasNext(isOperator)) {
|
||||
while (
|
||||
in.hasNext(isOperator) &&
|
||||
isInfixOp(min)(in.peek)
|
||||
) {
|
||||
val (op, pos) = getOperator
|
||||
Prim(op, res, parseUAtom).withPos(pos)
|
||||
res = Prim(op, res, parseExpression(prec(op))).withPos(pos)
|
||||
}
|
||||
res
|
||||
}
|
||||
@@ -538,7 +541,9 @@ class BranchParser(in: Scanner) extends LetParser(in) {
|
||||
}
|
||||
|
||||
// TODO: remove ??? and complete the implementation.
|
||||
override def parseSimpleExpression: Exp = in.peek match {
|
||||
override def parseSimpleExpression: Exp = {
|
||||
print(in.peek)
|
||||
in.peek match {
|
||||
case Keyword("if") =>
|
||||
val pos = in.next().pos
|
||||
accept('(')
|
||||
@@ -546,6 +551,7 @@ class BranchParser(in: Scanner) extends LetParser(in) {
|
||||
accept(')')
|
||||
val if_stmt = parseSimpleExpression
|
||||
if (in.hasNext(_ == Keyword("else"))) {
|
||||
in.next()
|
||||
val else_stmt = parseSimpleExpression
|
||||
If(cond, if_stmt, else_stmt).withPos(pos)
|
||||
}
|
||||
@@ -553,6 +559,7 @@ class BranchParser(in: Scanner) extends LetParser(in) {
|
||||
case _ => super.parseSimpleExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We can now introduce mutable variables using the 'var' keyword.
|
||||
@@ -596,9 +603,10 @@ class VariableParser(in: Scanner) extends BranchParser(in) {
|
||||
// TODO: remove ??? and complete the implementation.
|
||||
override def parseSimpleExpression = (in.peek, in.peek1) match {
|
||||
case (Ident(x), Delim('=')) =>
|
||||
val pos:Position = in.peek.pos
|
||||
val pos:Position = in.next().pos
|
||||
accept('=')
|
||||
VarAssign(x, parseSimpleExpression).withPos(pos)
|
||||
case _ => super.parseExpression
|
||||
case _ => super.parseSimpleExpression
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,6 +643,7 @@ class LoopParser(in: Scanner) extends VariableParser(in) {
|
||||
val cond = parseCondition
|
||||
accept(')')
|
||||
val simp = parseSimpleExpression
|
||||
accept(';')
|
||||
val body = parseExpression
|
||||
While(cond, simp, body).withPos(pos)
|
||||
case _ =>
|
||||
|
||||
@@ -121,22 +121,22 @@ class SemanticAnalyzer(parser: Parser) extends Reporter {
|
||||
analyze(v)(env)
|
||||
case Prim(op, lop, rop) => // Done
|
||||
if(!(isOperator(op) || isBOperator(op)))
|
||||
error("undefined primitive operator")
|
||||
error("undefined primitive operator", exp.pos)
|
||||
analyze(lop)(env)
|
||||
analyze(rop)(env)
|
||||
case Let(x, a, b) => // val x = a; b
|
||||
// Done: check variable reuse
|
||||
if(!env.vars.contains(x))
|
||||
error(s"cannot assign variable $x")
|
||||
if(env.vars.contains(x))
|
||||
error(s"cannot assign variable $x", exp.pos)
|
||||
analyze(a)(env)
|
||||
analyze(b)(env.withVal(x))
|
||||
case Ref(x) =>
|
||||
if (!env.vars.contains(x))
|
||||
error(s"symbol $x not defined")
|
||||
error(s"symbol $x not defined", exp.pos)
|
||||
// Done
|
||||
case Cond(op, l, r) =>
|
||||
if (!isBOperator(op))
|
||||
error(s"$op is not a boolean operator")
|
||||
error(s"$op is not a boolean operator", exp.pos)
|
||||
analyze(l)(env)
|
||||
analyze(r)(env)
|
||||
// Done
|
||||
@@ -146,13 +146,13 @@ class SemanticAnalyzer(parser: Parser) extends Reporter {
|
||||
analyze(eBranch)(env)
|
||||
case VarDec(x, rhs, body) => // var x = rhs; body
|
||||
if (env.vars.contains(x))
|
||||
error(s"symbol $x already defined")
|
||||
error(s"symbol $x already defined", exp.pos)
|
||||
analyze(rhs)(env)
|
||||
analyze(body)(env)
|
||||
analyze(body)(env.withVar(x))
|
||||
// TODO
|
||||
case VarAssign(x, rhs) => // x = rhs
|
||||
if (!(env.vars.contains(x) && env.vars(x)))
|
||||
error(s"cannot assign $x: ${if(env.vars.contains(x))"immutable"else"undefined"}")
|
||||
error(s"cannot assign $x: ${if(env.vars.contains(x))"immutable"else"undefined"}", exp.pos)
|
||||
analyze(rhs)(env)
|
||||
// TODO
|
||||
case While(cond, lBody, body) =>
|
||||
|
||||
Reference in New Issue
Block a user