Add Cast. Add ParserExpr and convert it to Expr after parsing
This commit is contained in:
parent
39c5a0527d
commit
b5083ba46a
@ -13,6 +13,7 @@ final case class LocalVar(x: String) extends Expr
|
||||
final case class FieldVar(e: Expr, f: String) extends Expr
|
||||
final case class MethodCall(e: Expr, name: String, params: List[Expr]) extends Expr
|
||||
final case class Constructor(className: String, params: List[Expr]) extends Expr
|
||||
final case class Cast(to: Type, expr: Expr) extends Expr
|
||||
|
||||
object ASTBuilder {
|
||||
def fromParseTree(toAst: List[ParserClass]) = new ASTBuilderMonad().fromParseTree(toAst)
|
||||
@ -27,9 +28,17 @@ object ASTBuilder {
|
||||
nTypeToType(c.superType, genericNames).asInstanceOf[RefType],
|
||||
c.fields.map(f => (nTypeToType(f._1, genericNames),f._2)), c.methods.map(m => Method(List(), freshTPV(), m.name,
|
||||
m.params.map(p => (p._1.map(it => nTypeToType(it, genericNames)).getOrElse(freshTPV()), p._2)),
|
||||
m.retExpr)))
|
||||
fromParseExpr(m.retExpr, genericNames))))
|
||||
})
|
||||
|
||||
def fromParseExpr(from: ParserExpr, genericNames: Set[String]): Expr = from match{
|
||||
case PMethodCall(e, name, params) => MethodCall(fromParseExpr(e, genericNames), name, params.map(fromParseExpr(_, genericNames)))
|
||||
case PConstructor(className, params) => Constructor(className, params.map(fromParseExpr(_, genericNames)))
|
||||
case PFieldVar(e, f) => FieldVar(fromParseExpr(e, genericNames), f)
|
||||
case PCast(ntype, e) => Cast(nTypeToType(ntype, genericNames), fromParseExpr(e, genericNames))
|
||||
case PLocalVar(n) => LocalVar(n)
|
||||
}
|
||||
|
||||
private def freshTPV() = {
|
||||
def numToLetter(num: Int) = {
|
||||
val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
@ -29,7 +29,7 @@ object FJTypeinference {
|
||||
private def convertSingleConstraint(constraint: Constraint) = constraint match {
|
||||
case LessDot(l, r) => UnifyLessDot(convertType(l),convertType(r))
|
||||
case EqualsDot(l, r) => UnifyEqualsDot(convertType(l),convertType(r))
|
||||
case _ => throw new Exception("Error: Möglicherweise zu tiefe Verschachtelung von OrConstraints")
|
||||
case _ => throw new Exception("Error: Internal Error considering Or-Constraints")
|
||||
}
|
||||
|
||||
private def generateFC(ast: List[Class]): FiniteClosure = new FiniteClosure(
|
||||
|
@ -4,10 +4,19 @@ import fastparse._, fastparse.ScalaWhitespace._
|
||||
|
||||
final case class ParserClass(name: String, params: List[(NType,NType)], superType: NType, fields: List[(NType,String)], methods: List[ParserMethod])
|
||||
|
||||
final case class ParserMethod(retType: Option[NType], name: String, params: List[(Option[NType], String)], retExpr: Expr)
|
||||
final case class ParserMethod(retType: Option[NType], name: String, params: List[(Option[NType], String)], retExpr: ParserExpr)
|
||||
|
||||
sealed trait ParserExpr
|
||||
final case class PLocalVar(x: String) extends ParserExpr
|
||||
final case class PFieldVar(e: ParserExpr, f: String) extends ParserExpr
|
||||
final case class PMethodCall(e: ParserExpr, name: String, params: List[ParserExpr]) extends ParserExpr
|
||||
final case class PConstructor(className: String, params: List[ParserExpr]) extends ParserExpr
|
||||
final case class PCast(to: NType, expr: ParserExpr) extends ParserExpr
|
||||
|
||||
final case class NType(name: String, params: List[NType])
|
||||
|
||||
object Parser {
|
||||
val keywords = Set("class", "new", "extends", "return")
|
||||
def kw[_: P](s: String) = s ~~ !(letter | digit)
|
||||
|
||||
def letter[_: P] = P( lowercase | uppercase )
|
||||
@ -16,24 +25,25 @@ object Parser {
|
||||
def digit[_: P] = P( CharIn("0-9") )
|
||||
def number[_: P]: P[Int] = P( CharIn("0-9").repX(1).!.map(_.toInt) )
|
||||
def ident[_: P]: P[String] =
|
||||
P( (letter) ~~ (letter | digit).repX ).!
|
||||
P( (letter) ~~ (letter | digit).repX ).!.filter(!keywords(_))
|
||||
|
||||
def fieldVar[_: P]: P[Expr] = P( ".".! ~ ident ).map(ite => FieldVar(null, ite._2) )
|
||||
def prefixMethodCall[_: P]: P[Expr] = P( "." ~ methodCall)
|
||||
def methodCall[_: P]: P[MethodCall] = P( ident ~ paramList ).map(ite => MethodCall(null, ite._1, ite._2) )
|
||||
def paramList[_: P] : P[List[Expr]] =
|
||||
def fieldVar[_: P]: P[ParserExpr] = P( ".".! ~ ident ).map(ite => PFieldVar(null, ite._2) )
|
||||
def prefixMethodCall[_: P]: P[ParserExpr] = P( "." ~ methodCall)
|
||||
def methodCall[_: P]: P[PMethodCall] = P( ident ~ paramList ).map(ite => PMethodCall(null, ite._1, ite._2) )
|
||||
def paramList[_: P] : P[List[ParserExpr]] =
|
||||
P("(".! ~ (expr ~ (",".! ~ expr).rep.map(_.toList.map{_._2})).? ~ ")".! )
|
||||
.map(ite => ite._2.map(params => params._1 :: params._2).getOrElse(List.empty))
|
||||
def variable[_: P]: P[Expr] = P(ident).map(LocalVar)
|
||||
def expr[_: P]: P[Expr] = P( (variable | constructor)~ (prefixMethodCall | fieldVar).rep.map(_.toList) )
|
||||
.map(ite => ite._2.foldLeft(ite._1) { (e1 : Expr, e2 : Expr) =>
|
||||
def variable[_: P]: P[ParserExpr] = P(ident).map(PLocalVar)
|
||||
def cast[_: P]: P[ParserExpr] = P("(" ~ typeParser ~ ")" ~ expr).map(x => PCast(x._1, x._2))
|
||||
def expr[_: P]: P[ParserExpr] = P( (variable | constructor | cast)~ (prefixMethodCall | fieldVar).rep.map(_.toList) )
|
||||
.map(ite => ite._2.foldLeft(ite._1) { (e1 : ParserExpr, e2 : ParserExpr) =>
|
||||
e2 match{
|
||||
case MethodCall(_, name, e3) => MethodCall(e1, name, e3)
|
||||
case FieldVar(_, name) => FieldVar(e1, name)
|
||||
case PMethodCall(_, name, e3) => PMethodCall(e1, name, e3)
|
||||
case PFieldVar(_, name) => PFieldVar(e1, name)
|
||||
}
|
||||
})
|
||||
|
||||
def constructor[_: P]: P[Expr] = P( kw("new") ~ methodCall).map(m => Constructor(m.name,m.params))
|
||||
def constructor[_: P]: P[ParserExpr] = P( kw("new") ~ methodCall).map(m => PConstructor(m.name,m.params))
|
||||
|
||||
def classDefinition[_: P]: P[ParserClass] = P(kw("class") ~ ident ~ genericParamList.? ~ kw("extends") ~ typeParser ~ "{" ~ field.rep(0) ~ method.rep(0) ~ "}")
|
||||
.map(ite => ParserClass(ite._1, ite._2.getOrElse(List()),ite._3, ite._4.toList, ite._5.toList))
|
||||
@ -53,7 +63,7 @@ object Parser {
|
||||
def program[_: P]: P[List[ParserClass]] = "" ~ classDefinition.rep(1).map(_.toList) ~ End
|
||||
|
||||
def parse(input: String): Either[String, List[ParserClass]] = fastparse.parse(input, program(_)).fold(
|
||||
(_, _, extra) => Left(s"Parser Error: $extra"),
|
||||
(_, _, extra) => Left(s"Parser Error: ${extra.toString}"),
|
||||
(v, _) => Right(v)
|
||||
)
|
||||
}
|
||||
|
@ -88,6 +88,10 @@ object TYPE {
|
||||
cl.genericParams.map(gp => LessDot(gp._1, gp._2))
|
||||
(RefType(className, cl.genericParams.map(_._1).map(genericReplace.replaceGenerics(_))), genericReplace.replaceGenerics(retCons))
|
||||
}
|
||||
case Cast(casttype, expr) => {
|
||||
val (rty, cons) = TYPEExpr(expr, localVars, ast)
|
||||
(casttype, cons)
|
||||
}
|
||||
}
|
||||
|
||||
private def findMethods(m: String, numParams: Int, ast: List[Class]) =
|
||||
|
@ -59,15 +59,13 @@ class IntegrationTest extends FunSuite {
|
||||
val result = FJTypeinference.typeinference(input )
|
||||
println(result.map(Main.prettyPrint(_)))
|
||||
}
|
||||
*/
|
||||
|
||||
test("constructor.FieldInitialization") {
|
||||
val input = "class List<A extends Object> extends Object{\nA f;\n add(a){\n return new List(a);\n}\n}"
|
||||
val result = FJTypeinference.typeinference(input )
|
||||
println(result.map(Main.prettyPrint(_)))
|
||||
println(result.map(it => Main.prettyPrintAST(it._2)))
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
test("list.add") {
|
||||
val input = "class List<A extends Object> extends Object{\nA f;\n add( a){\n return new List(a);\n}\n}\nclass Test extends Object{\n\nm(a){return a.add(this);}\n}"
|
||||
val result = FJTypeinference.typeinference(input )
|
||||
|
@ -8,11 +8,13 @@ class ParserTest extends FunSuite {
|
||||
}
|
||||
|
||||
test("Parser.methodCall"){
|
||||
println(fastparse.parse(("e.m(a)"), hb.dhbw.Parser.methodCall(_)))
|
||||
println(fastparse.parse(("e.m(a)"), hb.dhbw.Parser.expr(_)))
|
||||
}
|
||||
|
||||
test("Parser.constructor"){
|
||||
println(fastparse.parse(("new Test(a)"), hb.dhbw.Parser.constructor(_)))
|
||||
println(fastparse.parse("new List(this)", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("m(){return new List(this);}", hb.dhbw.Parser.method(_)))
|
||||
}
|
||||
|
||||
test("Parser.constructorExpression"){
|
||||
@ -22,6 +24,13 @@ class ParserTest extends FunSuite {
|
||||
test("Parser.type"){
|
||||
println(fastparse.parse("Test<Test<Object>>", hb.dhbw.Parser.typeParser(_)))
|
||||
}
|
||||
test("Parser.cast"){
|
||||
println(fastparse.parse("(Test<Test<Object>>) m", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("(Test<Test<Object>>) this.m()", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("(X)(Test<Test<X>>) m.f", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("(Test<Object>)(X) this", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("class Test extends Object{ m(){return (Test<Object>)(X) this;}}", hb.dhbw.Parser.program(_)))
|
||||
}
|
||||
|
||||
test("Parser.method"){
|
||||
println(fastparse.parse("m(a,b){return a;}", hb.dhbw.Parser.method(_)))
|
||||
@ -48,4 +57,9 @@ class ParserTest extends FunSuite {
|
||||
println(fastparse.parse("this", hb.dhbw.Parser.expr(_)))
|
||||
println(fastparse.parse("this.m()", hb.dhbw.Parser.expr(_)))
|
||||
}
|
||||
|
||||
test("Parser.test"){
|
||||
println(fastparse.parse("class List<A extends Object> extends Object{asd(){ return this; }get(){ return this.head;}}"
|
||||
, hb.dhbw.Parser.program(_)))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user