Example

Mathematical Expressions

Small expression language.

← All examples

Specification

$flags: 'OPTIONAL_WHITESPACE'

Token:
  Identifier: '[A-Za-z][A-Za-z0-9_]*'

Expression:

  Number: '\d+(\.\d+)?'

  Variable: '${Identifier}(?!\s*\()'

  FunctionCall:
    $fields: { name: Token::Identifier, arguments: 'Expression[]' }
    $patterns: '#{name}\( (#{arguments}(, #{arguments})*)? \)'

  Grouped:
    $fields: { value: Expression }
    $patterns: '\( #{value} \)'

  Power:
    $fields: { base: Expression, exponent: Expression }
    $patterns: '#{base} \^ #{exponent}'

  Product:
    $types:
      MultiplicativeOperator: '\*|/'
      Factor:
        $fields: { operator: MultiplicativeOperator, value: Expression }
        $patterns: '#{operator} #{value}'
    $fields: { first: Expression, factors: 'Factor[]' }
    $patterns: '#{first}( #{factors})+'

  Sum:
    $types:
      AdditiveOperator: '[+-]'
      Term:
        $fields: { operator: AdditiveOperator, value: Expression }
        $patterns: '#{operator} #{value}'
    $fields: { first: Expression, terms: 'Term[]' }
    $patterns: '#{first}( #{terms})+'

Statement:

  Assignment:
    $fields: { target: Variable, value: Expression }
    $patterns: '#{target} = #{value}'

  FunctionDefinition:
    $fields: { target: FunctionCall, value: Expression }
    $patterns: '#{target} = #{value}'

  Comparison:
    $types: { ComparisonOperator: '>=|<=|<>|!=|=|>|<' }
    $fields: { left: Expression, operator: ComparisonOperator, right: Expression }
    $patterns: '#{left} #{operator} #{right}'

Sample input

f(x) = (x + 3)^2
y = x^2 + pi/2*x - 4
sin(x) >= cos(y)
result = min(avg(a, b), max(c, d))
area = pi * r^2

Result

[
  {
    "type": "Statement::FunctionDefinition",
    "text": "f(x) = (x + 3)^2",
    "start": 0,
    "end": 16,
    "fields": [
      {
        "type": "Expression::FunctionCall",
        "field": "target",
        "text": "f(x)",
        "start": 0,
        "end": 4,
        "fields": [
          {
            "type": "Token::Identifier",
            "field": "name",
            "text": "f",
            "start": 0,
            "end": 1
          },
          {
            "type": "Expression[]",
            "field": "arguments",
            "text": "x",
            "start": 2,
            "end": 3,
            "items": [
              {
                "type": "Expression::Variable",
                "text": "x",
                "start": 2,
                "end": 3
              }
            ]
          }
        ]
      },
      {
        "type": "Expression::Power",
        "field": "value",
        "text": "(x + 3)^2",
        "start": 7,
        "end": 16,
        "fields": [
          {
            "type": "Expression::Grouped",
            "field": "base",
            "text": "(x + 3)",
            "start": 7,
            "end": 14,
            "fields": [
              {
                "type": "Expression::Sum",
                "field": "value",
                "text": "x + 3",
                "start": 8,
                "end": 13,
                "fields": [
                  {
                    "type": "Expression::Variable",
                    "field": "first",
                    "text": "x",
                    "start": 8,
                    "end": 9
                  },
                  {
                    "type": "Term[]",
                    "field": "terms",
                    "text": "+ 3",
                    "start": 10,
                    "end": 13,
                    "items": [
                      {
                        "type": "Term",
                        "text": "+ 3",
                        "start": 10,
                        "end": 13,
                        "fields": [
                          {
                            "type": "AdditiveOperator",
                            "field": "operator",
                            "text": "+",
                            "start": 10,
                            "end": 11
                          },
                          {
                            "type": "Expression::Number",
                            "field": "value",
                            "text": "3",
                            "start": 12,
                            "end": 13
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Expression::Number",
            "field": "exponent",
            "text": "2",
            "start": 15,
            "end": 16
          }
        ]
      }
    ]
  },
  {
    "type": "Statement::Assignment",
    "text": "y = x^2 + pi/2*x - 4",
    "start": 17,
    "end": 37,
    "fields": [
      {
        "type": "Expression::Variable",
        "field": "target",
        "text": "y",
        "start": 17,
        "end": 18
      },
      {
        "type": "Expression::Sum",
        "field": "value",
        "text": "x^2 + pi/2*x - 4",
        "start": 21,
        "end": 37,
        "fields": [
          {
            "type": "Expression::Power",
            "field": "first",
            "text": "x^2",
            "start": 21,
            "end": 24,
            "fields": [
              {
                "type": "Expression::Variable",
                "field": "base",
                "text": "x",
                "start": 21,
                "end": 22
              },
              {
                "type": "Expression::Number",
                "field": "exponent",
                "text": "2",
                "start": 23,
                "end": 24
              }
            ]
          },
          {
            "type": "Term[]",
            "field": "terms",
            "text": "+ pi/2*x - 4",
            "start": 25,
            "end": 37,
            "items": [
              {
                "type": "Term",
                "text": "+ pi/2*x",
                "start": 25,
                "end": 33,
                "fields": [
                  {
                    "type": "AdditiveOperator",
                    "field": "operator",
                    "text": "+",
                    "start": 25,
                    "end": 26
                  },
                  {
                    "type": "Expression::Product",
                    "field": "value",
                    "text": "pi/2*x",
                    "start": 27,
                    "end": 33,
                    "fields": [
                      {
                        "type": "Expression::Variable",
                        "field": "first",
                        "text": "pi",
                        "start": 27,
                        "end": 29
                      },
                      {
                        "type": "Factor[]",
                        "field": "factors",
                        "text": "/2*x",
                        "start": 29,
                        "end": 33,
                        "items": [
                          {
                            "type": "Factor",
                            "text": "/2",
                            "start": 29,
                            "end": 31,
                            "fields": [
                              {
                                "type": "MultiplicativeOperator",
                                "field": "operator",
                                "text": "/",
                                "start": 29,
                                "end": 30
                              },
                              {
                                "type": "Expression::Number",
                                "field": "value",
                                "text": "2",
                                "start": 30,
                                "end": 31
                              }
                            ]
                          },
                          {
                            "type": "Factor",
                            "text": "*x",
                            "start": 31,
                            "end": 33,
                            "fields": [
                              {
                                "type": "MultiplicativeOperator",
                                "field": "operator",
                                "text": "*",
                                "start": 31,
                                "end": 32
                              },
                              {
                                "type": "Expression::Variable",
                                "field": "value",
                                "text": "x",
                                "start": 32,
                                "end": 33
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              {
                "type": "Term",
                "text": "- 4",
                "start": 34,
                "end": 37,
                "fields": [
                  {
                    "type": "AdditiveOperator",
                    "field": "operator",
                    "text": "-",
                    "start": 34,
                    "end": 35
                  },
                  {
                    "type": "Expression::Number",
                    "field": "value",
                    "text": "4",
                    "start": 36,
                    "end": 37
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "type": "Statement::Comparison",
    "text": "sin(x) >= cos(y)",
    "start": 38,
    "end": 54,
    "fields": [
      {
        "type": "Expression::FunctionCall",
        "field": "left",
        "text": "sin(x)",
        "start": 38,
        "end": 44,
        "fields": [
          {
            "type": "Token::Identifier",
            "field": "name",
            "text": "sin",
            "start": 38,
            "end": 41
          },
          {
            "type": "Expression[]",
            "field": "arguments",
            "text": "x",
            "start": 42,
            "end": 43,
            "items": [
              {
                "type": "Expression::Variable",
                "text": "x",
                "start": 42,
                "end": 43
              }
            ]
          }
        ]
      },
      {
        "type": "ComparisonOperator",
        "field": "operator",
        "text": ">=",
        "start": 45,
        "end": 47
      },
      {
        "type": "Expression::FunctionCall",
        "field": "right",
        "text": "cos(y)",
        "start": 48,
        "end": 54,
        "fields": [
          {
            "type": "Token::Identifier",
            "field": "name",
            "text": "cos",
            "start": 48,
            "end": 51
          },
          {
            "type": "Expression[]",
            "field": "arguments",
            "text": "y",
            "start": 52,
            "end": 53,
            "items": [
              {
                "type": "Expression::Variable",
                "text": "y",
                "start": 52,
                "end": 53
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "type": "Statement::Assignment",
    "text": "result = min(avg(a, b), max(c, d))",
    "start": 55,
    "end": 89,
    "fields": [
      {
        "type": "Expression::Variable",
        "field": "target",
        "text": "result",
        "start": 55,
        "end": 61
      },
      {
        "type": "Expression::FunctionCall",
        "field": "value",
        "text": "min(avg(a, b), max(c, d))",
        "start": 64,
        "end": 89,
        "fields": [
          {
            "type": "Token::Identifier",
            "field": "name",
            "text": "min",
            "start": 64,
            "end": 67
          },
          {
            "type": "Expression[]",
            "field": "arguments",
            "text": "avg(a, b), max(c, d)",
            "start": 68,
            "end": 88,
            "items": [
              {
                "type": "Expression::FunctionCall",
                "text": "avg(a, b)",
                "start": 68,
                "end": 77,
                "fields": [
                  {
                    "type": "Token::Identifier",
                    "field": "name",
                    "text": "avg",
                    "start": 68,
                    "end": 71
                  },
                  {
                    "type": "Expression[]",
                    "field": "arguments",
                    "text": "a, b",
                    "start": 72,
                    "end": 76,
                    "items": [
                      {
                        "type": "Expression::Variable",
                        "text": "a",
                        "start": 72,
                        "end": 73
                      },
                      {
                        "type": "Expression::Variable",
                        "text": "b",
                        "start": 75,
                        "end": 76
                      }
                    ]
                  }
                ]
              },
              {
                "type": "Expression::FunctionCall",
                "text": "max(c, d)",
                "start": 79,
                "end": 88,
                "fields": [
                  {
                    "type": "Token::Identifier",
                    "field": "name",
                    "text": "max",
                    "start": 79,
                    "end": 82
                  },
                  {
                    "type": "Expression[]",
                    "field": "arguments",
                    "text": "c, d",
                    "start": 83,
                    "end": 87,
                    "items": [
                      {
                        "type": "Expression::Variable",
                        "text": "c",
                        "start": 83,
                        "end": 84
                      },
                      {
                        "type": "Expression::Variable",
                        "text": "d",
                        "start": 86,
                        "end": 87
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "type": "Statement::Assignment",
    "text": "area = pi * r^2",
    "start": 90,
    "end": 105,
    "fields": [
      {
        "type": "Expression::Variable",
        "field": "target",
        "text": "area",
        "start": 90,
        "end": 94
      },
      {
        "type": "Expression::Product",
        "field": "value",
        "text": "pi * r^2",
        "start": 97,
        "end": 105,
        "fields": [
          {
            "type": "Expression::Variable",
            "field": "first",
            "text": "pi",
            "start": 97,
            "end": 99
          },
          {
            "type": "Factor[]",
            "field": "factors",
            "text": "* r^2",
            "start": 100,
            "end": 105,
            "items": [
              {
                "type": "Factor",
                "text": "* r^2",
                "start": 100,
                "end": 105,
                "fields": [
                  {
                    "type": "MultiplicativeOperator",
                    "field": "operator",
                    "text": "*",
                    "start": 100,
                    "end": 101
                  },
                  {
                    "type": "Expression::Power",
                    "field": "value",
                    "text": "r^2",
                    "start": 102,
                    "end": 105,
                    "fields": [
                      {
                        "type": "Expression::Variable",
                        "field": "base",
                        "text": "r",
                        "start": 102,
                        "end": 103
                      },
                      {
                        "type": "Expression::Number",
                        "field": "exponent",
                        "text": "2",
                        "start": 104,
                        "end": 105
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

Notes

# Mathematical Expressions

Recognize small expression statements: assignments, comparisons, calls, variables, and arithmetic.

## Notice

- `Expression` is the parent type for values.
- Concrete forms include numbers, variables, calls, sums, products, and powers.
- `Sum` and `Product` keep the first value separate from repeated operator/value terms.
- `Statement` separates assignment, function definition, and comparison.
- Fields such as `target`, `value`, `left`, `right`, and `operator` keep the result inspectable.

Try adding `sqrt(x^2 + y^2) >= 10`.