@@ -8,17 +8,16 @@ package viper.silver.parser
88
99import java .net .URL
1010import java .nio .file .{Files , Path , Paths }
11-
1211import viper .silver .ast .{FilePosition , LabelledOld , LineCol , NoPosition , Position , SourcePosition }
1312import viper .silver .parser .FastParserCompanion .{LW , LeadingWhitespace }
1413import viper .silver .plugin .{ParserPluginTemplate , SilverPluginManager }
15- import viper .silver .verifier .ParseError
14+ import viper .silver .verifier .{ ParseError , ParseWarning }
1615
1716import scala .collection .{immutable , mutable }
1817
1918case class ParseException (msg : String , pos : (Position , Position )) extends Exception
2019
21- case class SuffixedExpressionGenerator [E <: PExp ](func : PExp => E ) extends (PExp => PExp ) {
20+ case class SuffixedExpressionGenerator [+ E <: PExp ](func : PExp => E ) extends (PExp => PExp ) {
2221 override def apply (v1 : PExp ): E = func(v1)
2322}
2423
@@ -125,6 +124,7 @@ class FastParser {
125124 var _line_offset : Array [Int ] = null
126125 /** The file we are currently parsing (for creating positions later). */
127126 var _file : Path = null
127+ var _warnings : Seq [ParseWarning ] = Seq ()
128128
129129 def parse (s : String , f : Path , plugins : Option [SilverPluginManager ] = None ) = {
130130 // Strategy to handle imports
@@ -390,9 +390,8 @@ class FastParser {
390390
391391 def quoted [$ : P , T ](p : => P [T ]) = " \" " ~ p ~ " \" "
392392
393- def foldPExp [E <: PExp ](e : PExp , es : Seq [SuffixedExpressionGenerator [E ]]): E =
394- es.foldLeft(e) { (t, a) => a(t)
395- }.asInstanceOf [E ]
393+ def foldPExp [E <: PExp ](e : E , es : Seq [SuffixedExpressionGenerator [E ]]): E =
394+ es.foldLeft(e) { (t, a) => a(t) }
396395
397396 def isFieldAccess (obj : Any ) = {
398397 obj.isInstanceOf [PFieldAccess ]
@@ -481,49 +480,47 @@ class FastParser {
481480 def exp [$ : P ]: P [PExp ] = P (iteExpr)
482481
483482 def suffix [$ : P ]: P [SuffixedExpressionGenerator [PExp ]] =
484- P (FP (" ." ~ idnuse).map { case (pos, id) => SuffixedExpressionGenerator [PExp ]((e : PExp ) => PFieldAccess (e, id)(pos)) } |
485- FP (" [" ~ Pass ~ " .." ~/ exp ~ " ]" ).map { case (pos, n) => SuffixedExpressionGenerator [PExp ]((e : PExp ) => PSeqTake (e, n)(pos)) } |
486- FP (" [" ~ exp ~ " .." ~ Pass ~ " ]" ).map { case (pos, n) => SuffixedExpressionGenerator [PExp ]((e : PExp ) => PSeqDrop (e, n)(pos)) } |
487- FP (" [" ~ exp ~ " .." ~ exp ~ " ]" ).map { case (pos, (n, m)) => SuffixedExpressionGenerator [PExp ]((e : PExp ) => PSeqDrop (PSeqTake (e, m)(pos), n)(pos)) } |
488- FP (" [" ~ exp ~ " ]" ).map { case (pos, e1) => SuffixedExpressionGenerator [PExp ]((e0 : PExp ) => PLookup (e0, e1)(pos)) } |
489- FP (" [" ~ exp ~ " :=" ~ exp ~ " ]" ).map { case (pos, (i, v)) => SuffixedExpressionGenerator [PExp ]((e : PExp ) => PUpdate (e, i, v)(pos)) })
490-
491- /*
492- Maps:
493- def suffix[$: P]: P[SuffixedExpressionGenerator[PExp]] =
494- P(FP("." ~ idnuse).map { case (pos, id) => SuffixedExpressionGenerator[PExp]((e: PExp) => {
495- PFieldAccess(e, id)(pos)
496- }) } |
497- FP("[" ~ Pass ~ ".." ~/ exp ~ "]").map { case (pos, n) => SuffixedExpressionGenerator[PExp]((e: PExp) => PSeqTake(e, n)(pos)) } |
498- FP("[" ~ exp ~ ".." ~ Pass ~ "]").map { case (pos, n) => SuffixedExpressionGenerator[PExp]((e: PExp) => PSeqDrop(e, n)(pos)) } |
499- FP("[" ~ exp ~ ".." ~ exp ~ "]").map { case (pos, (n, m)) => SuffixedExpressionGenerator[PExp]((e: PExp) => PSeqDrop(PSeqTake(e, m)(), n)(pos)) } |
500- FP("[" ~ exp ~ "]").map { case (pos, e1) => SuffixedExpressionGenerator[PExp]((e0: PExp) => PSeqIndex(e0, e1)(pos)) } |
501- FP("[" ~ exp ~ ":=" ~ exp ~ "]").map { case (pos, (i, v)) => SuffixedExpressionGenerator[PExp]((e: PExp) => PSeqUpdate(e, i, v)(pos)) })
502- */
483+ P (FP (" ." ~ idnuse).map { case (pos, id) => SuffixedExpressionGenerator [PExp ](e => PFieldAccess (e, id)(e.pos._1, pos._2)) } |
484+ FP (" [" ~ Pass ~ " .." ~/ exp ~ " ]" ).map { case (pos, n) => SuffixedExpressionGenerator [PExp ](e => PSeqTake (e, n)(e.pos._1, pos._2)) } |
485+ FP (" [" ~ exp ~ " .." ~ Pass ~ " ]" ).map { case (pos, n) => SuffixedExpressionGenerator [PExp ](e => PSeqDrop (e, n)(e.pos._1, pos._2)) } |
486+ FP (" [" ~ exp ~ " .." ~ exp ~ " ]" ).map { case (pos, (n, m)) => SuffixedExpressionGenerator [PExp ](e => PSeqDrop (PSeqTake (e, m)(e.pos._1, pos._2), n)(e.pos._1, pos._2)) } |
487+ FP (" [" ~ exp ~ " ]" ).map { case (pos, e1) => SuffixedExpressionGenerator [PExp ](e0 => PLookup (e0, e1)(e0.pos._1, pos._2)) } |
488+ FP (" [" ~ exp ~ " :=" ~ exp ~ " ]" ).map { case (pos, (i, v)) => SuffixedExpressionGenerator [PExp ](e => PUpdate (e, i, v)(e.pos._1, pos._2)) })
503489
504- def suffixExpr [$ : P ]: P [PExp ] = P ((atom ~~~ suffix.lw.rep).map { case (fac, ss) => foldPExp[ PExp ] (fac, ss) })
490+ def suffixExpr [$ : P ]: P [PExp ] = P ((atom ~~~ suffix.lw.rep).map { case (fac, ss) => foldPExp(fac, ss) })
505491
506492 def termOp [$ : P ]: P [String ] = P (StringIn (" *" , " /" , " \\ " , " %" ).! )
507493
508- def term [$ : P ]: P [PExp ] = P ((suffixExpr ~~~ termd.lw.rep).map { case (a, ss) => foldPExp[ PExp ] (a, ss) })
494+ def term [$ : P ]: P [PExp ] = P ((suffixExpr ~~~ termd.lw.rep).map { case (a, ss) => foldPExp(a, ss) })
509495
510- def termd [$ : P ]: P [SuffixedExpressionGenerator [PExp ]] = FP (termOp ~ suffixExpr).map { case (pos, (op, id)) => SuffixedExpressionGenerator [ PExp ](( e : PExp ) => PBinExp (e, op, id)(pos)) }
496+ def termd [$ : P ]: P [SuffixedExpressionGenerator [PBinExp ]] = FP (termOp ~ suffixExpr).map { case (pos, (op, id)) => SuffixedExpressionGenerator (e => PBinExp (e, op, id)(e. pos._1, pos._2 )) }
511497
512498 def sumOp [$ : P ]: P [String ] = P (StringIn (" ++" , " +" , " -" ).! | keyword(" union" ).! | keyword(" intersection" ).! | keyword(" setminus" ).! | keyword(" subset" ).! )
513499
514- def sum [$ : P ]: P [PExp ] = P ((term ~~~ sumd.lw.rep).map { case (a, ss) => foldPExp[ PBinExp ] (a, ss) })
500+ def sum [$ : P ]: P [PExp ] = P ((term ~~~ sumd.lw.rep).map { case (a, ss) => foldPExp(a, ss) })
515501
516- def sumd [$ : P ]: P [SuffixedExpressionGenerator [PBinExp ]] = FP (sumOp ~ term).map { case (pos, (op, id)) => SuffixedExpressionGenerator [ PBinExp ](( e : PExp ) => PBinExp (e, op, id)(pos)) }
502+ def sumd [$ : P ]: P [SuffixedExpressionGenerator [PBinExp ]] = FP (sumOp ~ term).map { case (pos, (op, id)) => SuffixedExpressionGenerator (e => PBinExp (e, op, id)(e. pos._1, pos._2 )) }
517503
518504 def cmpOp [$ : P ] = P (StringIn (" <=" , " >=" , " <" , " >" ).! | keyword(" in" ).! )
519505
520- def cmpExp [$ : P ]: P [PExp ] = FP (sum ~~~ (cmpOp ~ cmpExp).lw.? ).map {
521- case (pos, (a, b)) => b match {
522- case Some (c) => PBinExp (a, c._1, c._2)(pos)
523- case None => a
524- }
506+ val cmpOps = Set (" <=" , " >=" , " <" , " >" , " in" )
507+
508+ def cmpd [$ : P ]: P [PExp => SuffixedExpressionGenerator [PBinExp ]] = FP (cmpOp ~ sum).map {
509+ case (pos, (op, right)) => chainComp(op, right, pos)
525510 }
526511
512+ def chainComp (op : String , right : PExp , pos : (FilePosition , FilePosition ))(from : PExp ) = SuffixedExpressionGenerator (_ match {
513+ case left@ PBinExp (_, op0, middle) if cmpOps.contains(op0) && left != from =>
514+ PBinExp (left, " &&" , PBinExp (middle, op, right)(middle.pos._1, pos._2))(left.pos._1, pos._2)
515+ case left@ PBinExp (_, " &&" , PBinExp (_, op0, middle)) if cmpOps.contains(op0) && left != from =>
516+ PBinExp (left, " &&" , PBinExp (middle, op, right)(middle.pos._1, pos._2))(left.pos._1, pos._2)
517+ case left => PBinExp (left, op, right)(left.pos._1, pos._2)
518+ })
519+
520+ def cmpExp [$ : P ]: P [PExp ] = P ((sum ~~~ cmpd.lw.rep).map {
521+ case (from, others) => foldPExp(from, others.map(_(from)))
522+ })
523+
527524 def eqOp [$ : P ] = P (StringIn (" ==" , " !=" ).! )
528525
529526 def eqExp [$ : P ]: P [PExp ] = FP (cmpExp ~~~ (eqOp ~ eqExp).lw.? ).map {
@@ -631,11 +628,15 @@ class FastParser {
631628 case (pos, (keyType, valueType)) => PMapType (keyType, valueType)(pos)
632629 }
633630
631+
634632 /** Only for call-like macros, `idnuse`-like ones are parsed by `domainTyp`. */
635633 def macroType [$ : P ] : P [PMacroType ] = funcApp.map(PMacroType (_))
636634
637- def primitiveTyp [$ : P ]: P [PPrimitiv ] = P (FP (keyword(" Rational" )).map{ case (pos, _) => PPrimitiv (" Perm" )(pos)}
638- | FP ((StringIn (" Int" , " Bool" , " Perm" , " Ref" ) ~~ ! identContinues).! ).map{ case (pos, name) => PPrimitiv (name)(pos)})
635+ def primitiveTyp [$ : P ]: P [PPrimitiv ] = P (FP (keyword(" Rational" )).map {
636+ case (pos, _) =>
637+ _warnings = _warnings :+ ParseWarning (" Rational is deprecated, use Perm instead" , SourcePosition (_file, pos._1.line, pos._1.column))
638+ PPrimitiv (" Perm" )(pos)
639+ } | FP ((StringIn (" Int" , " Bool" , " Perm" , " Ref" ) ~~ ! identContinues).! ).map { case (pos, name) => PPrimitiv (name)(pos) })
639640/* Maps:
640641 lazy val primitiveTyp: P[PType] = P(keyword("Rational").map(_ => PPrimitiv("Perm"))
641642 | (StringIn("Int", "Bool", "Perm", "Ref") ~~ !identContinues).!.map(PPrimitiv))
0 commit comments