Skip to content

Commit

Permalink
remove, simplify not needed methods
Browse files Browse the repository at this point in the history
  • Loading branch information
pawelkaczor committed Jan 23, 2021
1 parent efecc04 commit 62991c5
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 96 deletions.
82 changes: 23 additions & 59 deletions src/main/scala/br/com/virsox/scalexpr/ExpressionParser.scala
Expand Up @@ -35,10 +35,10 @@ class ExpressionParser extends DateParser {

def parseRelationalExpression(str: String): Try[RelationalExpression[_ >: Instant with String with BigDecimal]] =
parse(str, relationalExpr(_)) match {
case Parsed.Success(value, _) => Success(value)
case f: Parsed.Failure => //(_, _, _) => {
println(s"[${f.index}], ${f.extra.trace()}")
Failure(ExpressionParsingException("Error"))
case Parsed.Success(value, _) =>
Success(value)
case f: Parsed.Failure =>
Failure(ExpressionParsingException(s"[${f.index}], ${f.extra.trace()}"))
}

/** *
Expand All @@ -48,44 +48,23 @@ class ExpressionParser extends DateParser {
*/
def parseBooleanExpression(str: String): Try[Expression[Boolean]] =
parse(str, booleanExpr(_)) match {
case Parsed.Success(value, _) => Success(value)
case f: Parsed.Failure => //(_, _, _) => {
println(s"[${f.index}], ${f.extra.trace()}")
Failure(ExpressionParsingException("Error"))
case Parsed.Success(value, _) =>
Success(value)
case f: Parsed.Failure =>
Failure(ExpressionParsingException(s"[${f.index}], ${f.extra.trace()}"))
}

/** *
* Parse a String as a double expression.
* Parse a String as a BigDecimal expression.
* @param str String to be parsed.
* @return Double expression if the String can be successfully parsed, a Failure otherwise.
* @return BigDecimal expression if the String can be successfully parsed, a Failure otherwise.
*/

def parseDoubleExpression(str: String): Try[NumericExpr[Double]] =
parse(str, exprDouble(_)) match {
case Parsed.Success(value, _) => Success(value)
case Parsed.Failure(_, _, _) => Failure(ExpressionParsingException("Error"))
}

/** *
* Parse a String as a int expression.
* @param str String to be parsed.
* @return Int expression if the String can be successfully parsed, a Failure otherwise.
*/
def parseIntExpression(str: String): Try[Expression[Int]] =
parse(str, exprInt(_)) match {
case Parsed.Success(value, _) => Success(value)
case Parsed.Failure(_, _, _) => Failure(ExpressionParsingException("Error"))
}

/** *
* Parse a String as a long expression.
* @param str String to be parsed.
* @return Long expression if the String can be successfully parsed, a Failure otherwise.
*/
def parseLongExpression(str: String): Try[Expression[Long]] =
parse(str, exprLong(_)) match {
case Parsed.Success(value, _) => Success(value)
case Parsed.Failure(_, _, _) => Failure(ExpressionParsingException("Error"))
def parseArithmeticExpression(str: String): Try[Expression[BigDecimal]] =
parse(str, arithmeticExpr(_)) match {
case Parsed.Success(value, _) =>
Success(value)
case f: Parsed.Failure =>
Failure(ExpressionParsingException(s"[${f.index}], ${f.extra.trace()}"))
}

// ---------------------------------------------------------------
Expand Down Expand Up @@ -150,30 +129,26 @@ class ExpressionParser extends DateParser {
* @tparam T Type of the variable returned by the parser.
* @return numeric variable parser.
*/
def numericVariable[_: P, T: TypeTag]: P[NumericExpr[T]] = {
val tt = implicitly[TypeTag[T]]
tt.tpe match {
def numericVariable[_: P, T: TypeTag]: P[NumericExpr[T]] =
implicitly[TypeTag[T]].tpe match {
case _ if typeOf[T] =:= typeOf[Int] => intVariable.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[Long] => longVariable.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[Double] => doubleVariable.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[BigDecimal] => bigDecimalVariable.asInstanceOf[P[NumericExpr[T]]]
}
}

/** *
* Obtains a numeric literal parser based on the informed type.
* @tparam T Type of the literal returned by the parser.
* @return numeric literal parser.
*/
def numericLiteral[_: P, T: TypeTag]: P[NumericExpr[T]] = {
val tt = implicitly[TypeTag[T]]
tt.tpe match {
def numericLiteral[_: P, T: TypeTag]: P[NumericExpr[T]] =
implicitly[TypeTag[T]].tpe match {
case _ if typeOf[T] =:= typeOf[Int] => intLiteral.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[Long] => longLiteral.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[Double] => doubleLiteral.asInstanceOf[P[NumericExpr[T]]]
case _ if typeOf[T] =:= typeOf[BigDecimal] => bigDecimalLiteral.asInstanceOf[P[NumericExpr[T]]]
}
}

/** *
* Builds a ArithmeticExpression composed of a left-hand subexpression followed by a sequence of
Expand Down Expand Up @@ -206,9 +181,7 @@ class ExpressionParser extends DateParser {
def divMul[A: P, T: TypeTag]: P[NumericExpr[T]] = P(factor[A, T] ~ (CharIn("*/").! ~ factor[A, T]).rep).map(evalNumeric[T])

/** Parser for arithmetic expressions. */
def exprDouble[A: P]: P[NumericExpr[Double]] = numExpr[A, Double]
def exprInt[A: P]: P[NumericExpr[Int]] = numExpr[A, Int]
def exprLong[A: P]: P[NumericExpr[Long]] = numExpr[A, Long]
def arithmeticExpr[A: P]: P[NumericExpr[BigDecimal]] = numExpr[A, BigDecimal]

def numExpr[A: P, T: TypeTag]: P[NumericExpr[T]] = P(divMul[A, T] ~ (CharIn("+\\-").! ~ divMul[A, T]).rep).map(evalNumeric[T])

Expand Down Expand Up @@ -244,24 +217,15 @@ class ExpressionParser extends DateParser {
P((stringLiteral ~ relationalOperators.! ~ stringVariable) | (stringVariable ~ relationalOperators.! ~ stringLiteral))
.map(evalRelational[String])

def intRelationalExpr[A: P]: P[RelationalExpression[Int]] =
P(numExpr[A, Int] ~ relationalOperators.! ~ numExpr[A, Int]).map(evalRelational[Int])

def longRelationalExpr[A: P]: P[RelationalExpression[Long]] =
P(numExpr[A, Long] ~ relationalOperators.! ~ numExpr[A, Long]).map(evalRelational[Long])

def doubleRelationalExpr[A: P]: P[RelationalExpression[Double]] =
P(numExpr[A, Double] ~ relationalOperators.! ~ numExpr[A, Double]).map(evalRelational[Double])

def bigDecimalRelationalExpr[A: P]: P[RelationalExpression[BigDecimal]] =
def numericRelationalExpr[A: P]: P[RelationalExpression[BigDecimal]] =
P(numExpr[A, BigDecimal] ~ relationalOperators.! ~ numExpr[A, BigDecimal]).map(evalRelational[BigDecimal])

def dateTimeRelationalExpr[A: P]: P[RelationalExpression[Instant]] =
P((dateTimeLiteral ~ relationalOperators.! ~ dateTimeVariable) | (dateTimeVariable ~ relationalOperators.! ~ dateTimeLiteral))
.map(evalRelational[Instant])

def relationalExpr[_: P]: P[RelationalExpression[_ >: Instant with String with BigDecimal]] =
P(strRelationalExpr | dateTimeRelationalExpr | bigDecimalRelationalExpr)
P(strRelationalExpr | dateTimeRelationalExpr | numericRelationalExpr)

// ---------------------------------------------------------------
// ------------------ Boolean expressions --------------------
Expand Down
69 changes: 32 additions & 37 deletions src/test/scala/br/com/virsox/scalexpr/ExpressionParserTest.scala
Expand Up @@ -24,72 +24,67 @@ class ExpressionParserTest extends AnyFlatSpec with Matchers {
}
}

"An ExpressionParser" should "parse an int expression" in new Fixture {
verify(parser.parseIntExpression("5 +3"), IntConstant(5) + IntConstant(3))
"An ExpressionParser" should "parse an arithmetic expression" in new Fixture {
verify(parser.parseArithmeticExpression("5 +3"), BigDecimalConstant(5) + BigDecimalConstant(3))
}

it should "consider operator precedence in an int expression" in new Fixture {
verify(parser.parseIntExpression("4+1 * 2"), IntConstant(4) + (IntConstant(1) * IntConstant(2)))
it should "consider operator precedence in an arithmetic expression" in new Fixture {
verify(parser.parseArithmeticExpression("4+1 * 2"), BigDecimalConstant(4) + (BigDecimalConstant(1) * BigDecimalConstant(2)))
}

it should "consider parenthesis precedence in an int expression" in new Fixture {
it should "consider parenthesis precedence in an arithmetic expression" in new Fixture {
verify(
parser.parseIntExpression("3 * ((1 + 2) * (5 + 1))"),
IntConstant(3) *
((IntConstant(1) + IntConstant(2)) *
(IntConstant(5) + IntConstant(1)))
parser.parseArithmeticExpression("3 * ((1 + 2) * (5 + 1))"),
BigDecimalConstant(3) *
((BigDecimalConstant(1) + BigDecimalConstant(2)) *
(BigDecimalConstant(5) + BigDecimalConstant(1)))
)
}

it should "parse variables in an int expression" in new Fixture {
verify(parser.parseIntExpression("sourceId + 1 * 2"), IntVar("sourceId") + (IntConstant(1) * IntConstant(2)))
verify(
parser.parseArithmeticExpression("sourceId + 1 * 2"),
BigDecimalVar("sourceId") + (BigDecimalConstant(1) * BigDecimalConstant(2))
)
}

it should "resolve variables in an int expression with parenthesis" in new Fixture {
verify(
parser.parseIntExpression("3 * ((sourceId + 2) * (sourceId + 1))"),
IntConstant(3) *
((IntVar("sourceId") + IntConstant(2)) *
(IntVar("sourceId") + IntConstant(1)))
parser.parseArithmeticExpression("3 * ((sourceId + 2) * (sourceId + 1))"),
BigDecimalConstant(3) *
((BigDecimalVar("sourceId") + BigDecimalConstant(2)) *
(BigDecimalVar("sourceId") + BigDecimalConstant(1)))
)
}

it should "calculate a long expression" in new Fixture {
verify(parser.parseLongExpression("2L + 30L"), LongConstant(2) + LongConstant(30))
}

it should "resolve variables in a long expression" in new Fixture {
verify(parser.parseLongExpression("sourceId + 30L"), LongVar("sourceId") + LongConstant(30L))
it should "calculate an arithmetic expression" in new Fixture {
verify(parser.parseArithmeticExpression("2 + 30"), BigDecimalConstant(2) + BigDecimalConstant(30))
}

it should "parse a double expression" in new Fixture {
verify(parser.parseDoubleExpression("7.2 + 3.0"), DoubleConstant(7.2) + DoubleConstant(3.0))
it should "resolve variables in an arithmetic expression" in new Fixture {
verify(parser.parseArithmeticExpression("sourceId + 30"), BigDecimalVar("sourceId") + BigDecimalConstant(30))
}

it should "consider operator precedence in a double expression" in new Fixture {
verify(
parser.parseDoubleExpression("7.2 + 1.8*2.0"),
DoubleConstant(7.2) +
(DoubleConstant(1.8) * DoubleConstant(2.0))
)
it should "parse an arithmetic expression with doubles" in new Fixture {
verify(parser.parseArithmeticExpression("7.2 + 3.0"), BigDecimalConstant(7.2) + BigDecimalConstant(3.0))
}

it should "consider parenthesis precedence in a double expression" in new Fixture {
it should "consider operator precedence in an arithmetic expression with doubles" in new Fixture {
verify(
parser.parseDoubleExpression("(7.2 + 1.8)*2.0"),
(DoubleConstant(7.2) + DoubleConstant(1.8)) *
DoubleConstant(2.0)
parser.parseArithmeticExpression("7.2 + 1.8*2.0"),
BigDecimalConstant(7.2) +
(BigDecimalConstant(1.8) * BigDecimalConstant(2.0))
)
}

it should "resolve double variables in a double expression" in new Fixture {
verify(parser.parseDoubleExpression("value + 3.0"), DoubleVar("value") + DoubleConstant(3.0))
it should "resolve double variables in an arithmetic expression" in new Fixture {
verify(parser.parseArithmeticExpression("value + 3.0"), BigDecimalVar("value") + BigDecimalConstant(3.0))
}

it should "resolve multiple variables in a double expression with parenthesis" in new Fixture {
it should "resolve multiple variables in an arithmetic expression with parenthesis" in new Fixture {
verify(
parser.parseDoubleExpression("(value + 3.0 ) *sourceId"),
(DoubleVar("value") + DoubleConstant(3.0)) * DoubleVar("sourceId")
parser.parseArithmeticExpression("(value + 3.0 ) *sourceId"),
(BigDecimalVar("value") + BigDecimalConstant(3.0)) * BigDecimalVar("sourceId")
)
}

Expand Down

0 comments on commit 62991c5

Please sign in to comment.