SciJava Expression Parser

A general-purpose mathematical expression parser, which converts infix expression strings into postfix queues and/or syntax trees.

License

License

Simplified BSD License
GroupId

GroupId

org.scijava
ArtifactId

ArtifactId

scijava-expression-parser
Last Version

Last Version

3.1.0
Release Date

Release Date

Type

Type

jar
Description

Description

SciJava Expression Parser
A general-purpose mathematical expression parser, which converts infix expression strings into postfix queues and/or syntax trees.
Project URL

Project URL

https://github.com/scijava/scijava-expression-parser
Project Organization

Project Organization

SciJava
Source Code Management

Source Code Management

https://github.com/scijava/scijava-expression-parser

Download scijava-expression-parser

How to add to project

<!-- https://jarcasting.com/artifacts/org.scijava/scijava-expression-parser/ -->
<dependency>
    <groupId>org.scijava</groupId>
    <artifactId>scijava-expression-parser</artifactId>
    <version>3.1.0</version>
</dependency>
// https://jarcasting.com/artifacts/org.scijava/scijava-expression-parser/
implementation 'org.scijava:scijava-expression-parser:3.1.0'
// https://jarcasting.com/artifacts/org.scijava/scijava-expression-parser/
implementation ("org.scijava:scijava-expression-parser:3.1.0")
'org.scijava:scijava-expression-parser:jar:3.1.0'
<dependency org="org.scijava" name="scijava-expression-parser" rev="3.1.0">
  <artifact name="scijava-expression-parser" type="jar" />
</dependency>
@Grapes(
@Grab(group='org.scijava', module='scijava-expression-parser', version='3.1.0')
)
libraryDependencies += "org.scijava" % "scijava-expression-parser" % "3.1.0"
[org.scijava/scijava-expression-parser "3.1.0"]

Dependencies

test (1)

Group / Artifact Type Version
junit : junit jar 4.11

Project Modules

There are no modules declared in this project.

Parsington

Parsington is an infix-to-postfix (or infix-to-syntax-tree) expression parser for mathematical expressions written in Java. It is simple yet fancy, handling (customizable) operators, functions, variables and constants in a similar way to what the Java language itself supports.

Parsington is part of the SciJava project for scientific computing in Java.

Rationale

Expression parsers are as old as the hills; what makes this one different?

  • No dependencies.
  • Available on Maven Central.
  • Permissive BSD-2 license. See LICENSE.txt.
  • Separation of concerns. Parsington is a parser, not an evaluator. Once you have the postfix queue and/or syntax tree, what you do with it is your business (though there is a small evaluation API in the eval subpackage if that appeals to you). In general, there is no assumption that your variables will consist of any particular data type, numerical or otherwise.
  • Extensibility. The default operators, a synthesis of Java and MATLAB syntax, work well. But if you need something else, you can define your own unary and binary operators with whatever symbols, precedence and associativity you desire.
  • Clean, well-commented codebase with unit tests. Import the source into your favorite IDE and watch Parsington in action by putting a breakpoint here.

History

The ImageJ Ops project needed an expression parser so that it could be more awesome. But not one limited to primitive doubles, or one that conflated parsing with evaluation, or one licensed in a restrictive way. Just a simple infix parser: a nice shunting yard implementation, or maybe some lovely recursive descent. Something on GitHub, with no dependencies, available on Maven Central. But surprisingly, there was only tumbleweed. So Parsington was born, and all our problems are now over!

Usage

In your POM <dependencies>:

<dependency>
  <groupId>org.scijava</groupId>
  <artifactId>parsington</artifactId>
  <version>2.0.0</version>
</dependency>

Postfix queues

To parse an infix expression to a postfix queue:

LinkedList<Object> queue = new ExpressionParser().parsePostfix("a+b*c^f(1,2)'");
// queue = [a, b, c, f, 1, 2, (2), <Fn>, ^, ', *, +]

Syntax trees

To parse an infix expression to a syntax tree:

SyntaxTree tree = new ExpressionParser().parseTree("a+b*c^f(1,2)'");
       +-------+
       |   +   |
       +---+---+
           |
    +------+------+
    |             |
+---+---+     +---+---+
|   a   |     |   *   |
+-------+     +---+---+
                  |
           +------+------+
           |             |
       +---+---+     +---+---+
       |   b   |     |   '   |
       +-------+     +---+---+
                         |
                         |
                     +---+---+
                     |   ^   |
                     +---+---+
                         |
                  +------+------+
                  |             |
              +---+---+     +---+---+
              |   c   |     | <Fn>  |
              +-------+     +---+---+
                                |
                         +------+------+
                         |             |
                     +---+---+     +---+---+
                     |   f   |     |  (2)  |
                     +-------+     +---+---+
                                       |
                                +------+------+
                                |             |
                            +---+---+     +---+---+
                            |   1   |     |   2   |
                            +-------+     +-------+

Evaluation

To evaluate an expression involving basic types:

Object result = new DefaultEvaluator().evaluate("6.5*7.8^2.3");

Interactive console

There is also an interactive console shell you can play with.

Run it easily using jgo:

jgo org.scijava:parsington

Or run from source, after cloning this repository:

mvn
java -jar target/parsington-*-SNAPSHOT.jar

Simple example invocations with the console's default evaluator:

> 6.5*7.8^2.3
732.3706691398969 : java.lang.Double
> 2*3,4
      ^
Misplaced separator or mismatched groups at index 4

The postfix built-in function lets you introspect a parsed postfix queue:

> postfix('6.5*7.8^2.3')
6.5 : java.lang.Double
7.8 : java.lang.Double
2.3 : java.lang.Double
^ : org.scijava.parsington.Operator
* : org.scijava.parsington.Operator
> postfix('[1, 2f, 3d, 4., 5L, 123456789987654321, 9987654321234567899]')
1 : java.lang.Integer
2.0 : java.lang.Float
3.0 : java.lang.Double
4.0 : java.lang.Double
5 : java.lang.Long
123456789987654321 : java.lang.Long
9987654321234567899 : java.math.BigInteger
[7] : org.scijava.parsington.Group
> postfix('f(x, y) = x*y')
f : org.scijava.parsington.Variable
x : org.scijava.parsington.Variable
y : org.scijava.parsington.Variable
(2) : org.scijava.parsington.Group
<Fn> : org.scijava.parsington.Function
x : org.scijava.parsington.Variable
y : org.scijava.parsington.Variable
* : org.scijava.parsington.Operator
= : org.scijava.parsington.Operator
> postfix('math.pow(q) = q^q')
math : org.scijava.parsington.Variable
pow : org.scijava.parsington.Variable
. : org.scijava.parsington.Operator
q : org.scijava.parsington.Variable
(1) : org.scijava.parsington.Group
<Fn> : org.scijava.parsington.Function
q : org.scijava.parsington.Variable
q : org.scijava.parsington.Variable
^ : org.scijava.parsington.Operator
= : org.scijava.parsington.Operator

The tree function is another way to introspect, in syntax tree form:

> tree('math.pow(q) = q^q')
 '='
 - '<Fn>'
  -- '.'
   --- 'math'
   --- 'pow'
  -- '(1)'
   --- 'q'
 - '^'
  -- 'q'
  -- 'q'
 : org.scijava.parsington.SyntaxTree
org.scijava

SciJava

Scientific libraries in Java

Versions

Version
3.1.0
3.0.1
3.0.0
2.1.1
2.1.0
2.0.0