diff --git a/backend/requirements/base.in b/backend/requirements/base.in
index b354da553..ae390fd69 100644
--- a/backend/requirements/base.in
+++ b/backend/requirements/base.in
@@ -25,11 +25,11 @@ celery-redbeat==2.0.0
 service-identity==21.1.0
 regex==2021.8.3
 cryptography==36.0.1
-antlr4-python3-runtime==4.8.0
+antlr4-python3-runtime==4.9.3
 tqdm==4.62.3
 boto3==1.20.38
 django-storages==1.12.3
 django-health-check==3.16.5
 psutil==5.9.0
 dj-database-url==0.5.0
-redis==4.1.4
\ No newline at end of file
+redis==4.1.4
diff --git a/backend/requirements/base.txt b/backend/requirements/base.txt
index b5d0b3bab..fd8e7e6e0 100644
--- a/backend/requirements/base.txt
+++ b/backend/requirements/base.txt
@@ -10,7 +10,7 @@ aioredis==1.3.1
     # via channels-redis
 amqp==5.1.0
     # via kombu
-antlr4-python3-runtime==4.8.0
+antlr4-python3-runtime==4.9.3
     # via -r base.in
 asgiref==3.4.1
     # via
diff --git a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormula.py b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormula.py
index ac4fedb7d..84f97d759 100644
--- a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormula.py
+++ b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormula.py
@@ -1,4 +1,4 @@
-# Generated from BaserowFormula.g4 by ANTLR 4.8
+# Generated from BaserowFormula.g4 by ANTLR 4.9
 # encoding: utf-8
 from antlr4 import *
 from io import StringIO
@@ -188,7 +188,7 @@ class BaserowFormula ( Parser ):
 
     def __init__(self, input:TokenStream, output:TextIO = sys.stdout):
         super().__init__(input, output)
-        self.checkVersion("4.8")
+        self.checkVersion("4.9")
         self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache)
         self._predicates = None
 
diff --git a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaLexer.py b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaLexer.py
index 29bd2cfff..7a7773f37 100644
--- a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaLexer.py
+++ b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaLexer.py
@@ -1,4 +1,4 @@
-# Generated from BaserowFormulaLexer.g4 by ANTLR 4.8
+# Generated from BaserowFormulaLexer.g4 by ANTLR 4.9
 from antlr4 import *
 from io import StringIO
 from typing.io import TextIO
@@ -444,7 +444,7 @@ class BaserowFormulaLexer(Lexer):
 
     def __init__(self, input=None, output:TextIO = sys.stdout):
         super().__init__(input, output)
-        self.checkVersion("4.8")
+        self.checkVersion("4.9")
         self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
         self._actions = None
         self._predicates = None
diff --git a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaListener.py b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaListener.py
index 49182e875..22b81fd26 100644
--- a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaListener.py
+++ b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaListener.py
@@ -1,4 +1,4 @@
-# Generated from BaserowFormula.g4 by ANTLR 4.8
+# Generated from BaserowFormula.g4 by ANTLR 4.9
 from antlr4 import *
 if __name__ is not None and "." in __name__:
     from .BaserowFormula import BaserowFormula
diff --git a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaVisitor.py b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaVisitor.py
index 6c1b9e1a3..4e344d818 100644
--- a/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaVisitor.py
+++ b/backend/src/baserow/contrib/database/formula/parser/generated/BaserowFormulaVisitor.py
@@ -1,4 +1,4 @@
-# Generated from BaserowFormula.g4 by ANTLR 4.8
+# Generated from BaserowFormula.g4 by ANTLR 4.9
 from antlr4 import *
 if __name__ is not None and "." in __name__:
     from .BaserowFormula import BaserowFormula
diff --git a/changelog.md b/changelog.md
index e53090b6a..cb978e1d2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -25,6 +25,7 @@
 * **breaking change** The API endpoint `/api/database/formula/<field_id>/type/` now requires
   `table_id` instead of `field_id`, and also `name` in the request body.
 * Added support in dev.sh for KDE's Konsole terminal emulator.
+* Upgraded node runtime to v16.14.0
 
 ## Released (2022-03-03 1.9.1)
 
diff --git a/deploy/all-in-one/Dockerfile b/deploy/all-in-one/Dockerfile
index 2c0400124..85968d3f8 100644
--- a/deploy/all-in-one/Dockerfile
+++ b/deploy/all-in-one/Dockerfile
@@ -47,7 +47,7 @@ RUN apt-get update && \
     # ========================
     # Install Node
     # ========================
-    curl -fsSL https://deb.nodesource.com/setup_12.x | bash - && \
+    curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
     apt-get install --no-install-recommends -y nodejs && \
     apt-get clean && \
     rm -rf /var/lib/apt/lists/* && \
diff --git a/docs/development/intellij-setup.md b/docs/development/intellij-setup.md
index 97b563d5f..9a7c9dd2b 100644
--- a/docs/development/intellij-setup.md
+++ b/docs/development/intellij-setup.md
@@ -61,7 +61,7 @@ automatic style fixers to make your life as easy as possible.
 1. Now lets set up your frontend dev by changing directory to `baserow/web-frontend`
 1. Now run `yarn install` (if you do not have yarn available check out and install a
    node version manager like [nvm](https://github.com/nvm-sh/nvm) , baserow currently
-   uses node 12)
+   uses node 16)
 1. Select "Trust Project" if you see an IntelliJ popup after running yarn install
 1. Open your settings, search for and open the `Node.js and NPM` category and ensure the
    Node interpreter is pointing to the desired node executable
diff --git a/formula/Dockerfile b/formula/Dockerfile
index 14e543c72..283f378bd 100644
--- a/formula/Dockerfile
+++ b/formula/Dockerfile
@@ -15,9 +15,9 @@ RUN mkdir -p /workspace/src && chown -R $UID:$GID /workspace
 USER $UID:$GID
 WORKDIR /workspace
 
-ENV ANTLR_VERSION 4.8
+ENV ANTLR_VERSION 4.9
 ENV CLASSPATH .:/workspace/antlr-${ANTLR_VERSION}-complete.jar:$CLASSPATH
 
 RUN wget -q http://www.antlr.org/download/antlr-${ANTLR_VERSION}-complete.jar \
     && mv antlr-${ANTLR_VERSION}-complete.jar antlr.jar \
-    && chmod +x antlr.jar
\ No newline at end of file
+    && chmod +x antlr.jar
diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile.web-frontend b/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile.web-frontend
index faa6f1e82..fda30b470 100644
--- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile.web-frontend	
+++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile.web-frontend	
@@ -1,4 +1,4 @@
-FROM node:12
+FROM node:16
 
 ADD ./baserow /baserow
 ADD ./{{ cookiecutter.project_slug }} /{{ cookiecutter.project_slug }}
diff --git a/web-frontend/Dockerfile b/web-frontend/Dockerfile
index 60052536f..66bbbe72b 100644
--- a/web-frontend/Dockerfile
+++ b/web-frontend/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:12-buster as base
+FROM node:16-buster as base
 
 ARG UID
 ENV UID=${UID:-9999}
diff --git a/web-frontend/modules/database/formula/autocompleter/formulaAutocompleter.js b/web-frontend/modules/database/formula/autocompleter/formulaAutocompleter.js
index bd2119a2a..c3c23a40e 100644
--- a/web-frontend/modules/database/formula/autocompleter/formulaAutocompleter.js
+++ b/web-frontend/modules/database/formula/autocompleter/formulaAutocompleter.js
@@ -14,9 +14,9 @@
  * calculateFilteredFunctionsAndFieldsBasedOnCursorLocation which does step 1 and
  * autocompleteFormula which does step 2 given the results of step 1.
  */
-import { BaserowFormula } from '@baserow/modules/database/formula/parser/generated/BaserowFormula'
+import BaserowFormula from '@baserow/modules/database/formula/parser/generated/BaserowFormula'
 import { getTokenStreamForFormula } from '@baserow/modules/database/formula/parser/parser'
-import { BaserowFormulaLexer } from '@baserow/modules/database/formula/parser/generated/BaserowFormulaLexer'
+import BaserowFormulaLexer from '@baserow/modules/database/formula/parser/generated/BaserowFormulaLexer'
 
 function _countRemainingOpenBrackets(i, stop, stream, numOpenBrackets) {
   for (let k = i; k < stop; k++) {
diff --git a/web-frontend/modules/database/formula/parser/generated/BaserowFormula.js b/web-frontend/modules/database/formula/parser/generated/BaserowFormula.js
index 21f36560f..df5fb7d9f 100644
--- a/web-frontend/modules/database/formula/parser/generated/BaserowFormula.js
+++ b/web-frontend/modules/database/formula/parser/generated/BaserowFormula.js
@@ -1,62 +1,60 @@
-// Generated from BaserowFormula.g4 by ANTLR 4.8
+// Generated from BaserowFormula.g4 by ANTLR 4.9
 // jshint ignore: start
-var antlr4 = require('antlr4/index');
-var BaserowFormulaListener = require('./BaserowFormulaListener').BaserowFormulaListener;
-var BaserowFormulaVisitor = require('./BaserowFormulaVisitor').BaserowFormulaVisitor;
-
-var grammarFileName = "BaserowFormula.g4";
+import antlr4 from 'antlr4';
+import BaserowFormulaListener from './BaserowFormulaListener.js';
+import BaserowFormulaVisitor from './BaserowFormulaVisitor.js';
 
 
-var serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964",
-    "\u0003U]\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004\u0004\t\u0004",
-    "\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007\t\u0007\u0003\u0002",
-    "\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
+const serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786",
+    "\u5964\u0003U]\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004\u0004\t",
+    "\u0004\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007\t\u0007\u0003",
+    "\u0002\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
     "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
     "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
     "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
-    "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0005\u0003",
-    "-\n\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
-    "\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u00037\n\u0003\f\u0003\u000e",
-    "\u0003:\u000b\u0003\u0005\u0003<\n\u0003\u0003\u0003\u0003\u0003\u0005",
-    "\u0003@\n\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
+    "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0005",
+    "\u0003-\n\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
+    "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u00037\n\u0003\f\u0003",
+    "\u000e\u0003:\u000b\u0003\u0005\u0003<\n\u0003\u0003\u0003\u0003\u0003",
+    "\u0005\u0003@\n\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
     "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003",
-    "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0003P\n\u0003\f\u0003",
-    "\u000e\u0003S\u000b\u0003\u0003\u0004\u0003\u0004\u0003\u0005\u0003",
-    "\u0005\u0003\u0006\u0003\u0006\u0003\u0007\u0003\u0007\u0003\u0007\u0002",
-    "\u0003\u0004\b\u0002\u0004\u0006\b\n\f\u0002\n\u0003\u0002\u0006\u0007",
-    "\u0004\u0002\u0010\u0010KK\u0004\u0002??EE\u0004\u0002+,67\u0004\u0002",
-    "\'\'))\u0003\u0002\u0003\u0005\u0003\u0002\u001b\u001c\u0003\u0002\u001d",
-    "\u001e\u0002h\u0002\u000e\u0003\u0002\u0002\u0002\u0004?\u0003\u0002",
-    "\u0002\u0002\u0006T\u0003\u0002\u0002\u0002\bV\u0003\u0002\u0002\u0002",
-    "\nX\u0003\u0002\u0002\u0002\fZ\u0003\u0002\u0002\u0002\u000e\u000f\u0005",
-    "\u0004\u0003\u0002\u000f\u0010\u0007\u0002\u0002\u0003\u0010\u0003\u0003",
-    "\u0002\u0002\u0002\u0011\u0012\b\u0003\u0001\u0002\u0012@\u0007\u001b",
-    "\u0002\u0002\u0013@\u0007\u001c\u0002\u0002\u0014@\u0007\u0018\u0002",
-    "\u0002\u0015@\u0007\u0017\u0002\u0002\u0016@\t\u0002\u0002\u0002\u0017",
-    "\u0018\u0005\u0006\u0004\u0002\u0018\u0019\u0005\u0004\u0003\r\u0019",
-    "@\u0003\u0002\u0002\u0002\u001a\u001b\u0007\u0011\u0002\u0002\u001b",
-    "\u001c\u0005\u0004\u0003\u0002\u001c\u001d\u0007\u0012\u0002\u0002\u001d",
-    "@\u0003\u0002\u0002\u0002\u001e\u001f\u0007\b\u0002\u0002\u001f \u0007",
-    "\u0011\u0002\u0002 !\u0005\n\u0006\u0002!\"\u0007\u0012\u0002\u0002",
-    "\"@\u0003\u0002\u0002\u0002#$\u0007\t\u0002\u0002$%\u0007\u0011\u0002",
-    "\u0002%&\u0007\u0018\u0002\u0002&@\u0007\u0012\u0002\u0002\'(\u0007",
-    "\n\u0002\u0002()\u0007\u0011\u0002\u0002)*\u0005\n\u0006\u0002*,\u0007",
-    "\u000b\u0002\u0002+-\u0007\u0005\u0002\u0002,+\u0003\u0002\u0002\u0002",
-    ",-\u0003\u0002\u0002\u0002-.\u0003\u0002\u0002\u0002./\u0005\n\u0006",
-    "\u0002/0\u0007\u0012\u0002\u00020@\u0003\u0002\u0002\u000212\u0005\b",
-    "\u0005\u00022;\u0007\u0011\u0002\u000238\u0005\u0004\u0003\u000245\u0007",
-    "\u000b\u0002\u000257\u0005\u0004\u0003\u000264\u0003\u0002\u0002\u0002",
-    "7:\u0003\u0002\u0002\u000286\u0003\u0002\u0002\u000289\u0003\u0002\u0002",
-    "\u00029<\u0003\u0002\u0002\u0002:8\u0003\u0002\u0002\u0002;3\u0003\u0002",
-    "\u0002\u0002;<\u0003\u0002\u0002\u0002<=\u0003\u0002\u0002\u0002=>\u0007",
-    "\u0012\u0002\u0002>@\u0003\u0002\u0002\u0002?\u0011\u0003\u0002\u0002",
-    "\u0002?\u0013\u0003\u0002\u0002\u0002?\u0014\u0003\u0002\u0002\u0002",
-    "?\u0015\u0003\u0002\u0002\u0002?\u0016\u0003\u0002\u0002\u0002?\u0017",
-    "\u0003\u0002\u0002\u0002?\u001a\u0003\u0002\u0002\u0002?\u001e\u0003",
-    "\u0002\u0002\u0002?#\u0003\u0002\u0002\u0002?\'\u0003\u0002\u0002\u0002",
-    "?1\u0003\u0002\u0002\u0002@Q\u0003\u0002\u0002\u0002AB\f\n\u0002\u0002",
-    "BC\t\u0003\u0002\u0002CP\u0005\u0004\u0003\u000bDE\f\t\u0002\u0002E",
-    "F\t\u0004\u0002\u0002FP\u0005\u0004\u0003\nGH\f\b\u0002\u0002HI\t\u0005",
+    "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0003P\n\u0003",
+    "\f\u0003\u000e\u0003S\u000b\u0003\u0003\u0004\u0003\u0004\u0003\u0005",
+    "\u0003\u0005\u0003\u0006\u0003\u0006\u0003\u0007\u0003\u0007\u0003\u0007",
+    "\u0002\u0003\u0004\b\u0002\u0004\u0006\b\n\f\u0002\n\u0003\u0002\u0006",
+    "\u0007\u0004\u0002\u0010\u0010KK\u0004\u0002??EE\u0004\u0002+,67\u0004",
+    "\u0002\'\'))\u0003\u0002\u0003\u0005\u0003\u0002\u001b\u001c\u0003\u0002",
+    "\u001d\u001e\u0002h\u0002\u000e\u0003\u0002\u0002\u0002\u0004?\u0003",
+    "\u0002\u0002\u0002\u0006T\u0003\u0002\u0002\u0002\bV\u0003\u0002\u0002",
+    "\u0002\nX\u0003\u0002\u0002\u0002\fZ\u0003\u0002\u0002\u0002\u000e\u000f",
+    "\u0005\u0004\u0003\u0002\u000f\u0010\u0007\u0002\u0002\u0003\u0010\u0003",
+    "\u0003\u0002\u0002\u0002\u0011\u0012\b\u0003\u0001\u0002\u0012@\u0007",
+    "\u001b\u0002\u0002\u0013@\u0007\u001c\u0002\u0002\u0014@\u0007\u0018",
+    "\u0002\u0002\u0015@\u0007\u0017\u0002\u0002\u0016@\t\u0002\u0002\u0002",
+    "\u0017\u0018\u0005\u0006\u0004\u0002\u0018\u0019\u0005\u0004\u0003\r",
+    "\u0019@\u0003\u0002\u0002\u0002\u001a\u001b\u0007\u0011\u0002\u0002",
+    "\u001b\u001c\u0005\u0004\u0003\u0002\u001c\u001d\u0007\u0012\u0002\u0002",
+    "\u001d@\u0003\u0002\u0002\u0002\u001e\u001f\u0007\b\u0002\u0002\u001f",
+    " \u0007\u0011\u0002\u0002 !\u0005\n\u0006\u0002!\"\u0007\u0012\u0002",
+    "\u0002\"@\u0003\u0002\u0002\u0002#$\u0007\t\u0002\u0002$%\u0007\u0011",
+    "\u0002\u0002%&\u0007\u0018\u0002\u0002&@\u0007\u0012\u0002\u0002\'(",
+    "\u0007\n\u0002\u0002()\u0007\u0011\u0002\u0002)*\u0005\n\u0006\u0002",
+    "*,\u0007\u000b\u0002\u0002+-\u0007\u0005\u0002\u0002,+\u0003\u0002\u0002",
+    "\u0002,-\u0003\u0002\u0002\u0002-.\u0003\u0002\u0002\u0002./\u0005\n",
+    "\u0006\u0002/0\u0007\u0012\u0002\u00020@\u0003\u0002\u0002\u000212\u0005",
+    "\b\u0005\u00022;\u0007\u0011\u0002\u000238\u0005\u0004\u0003\u00024",
+    "5\u0007\u000b\u0002\u000257\u0005\u0004\u0003\u000264\u0003\u0002\u0002",
+    "\u00027:\u0003\u0002\u0002\u000286\u0003\u0002\u0002\u000289\u0003\u0002",
+    "\u0002\u00029<\u0003\u0002\u0002\u0002:8\u0003\u0002\u0002\u0002;3\u0003",
+    "\u0002\u0002\u0002;<\u0003\u0002\u0002\u0002<=\u0003\u0002\u0002\u0002",
+    "=>\u0007\u0012\u0002\u0002>@\u0003\u0002\u0002\u0002?\u0011\u0003\u0002",
+    "\u0002\u0002?\u0013\u0003\u0002\u0002\u0002?\u0014\u0003\u0002\u0002",
+    "\u0002?\u0015\u0003\u0002\u0002\u0002?\u0016\u0003\u0002\u0002\u0002",
+    "?\u0017\u0003\u0002\u0002\u0002?\u001a\u0003\u0002\u0002\u0002?\u001e",
+    "\u0003\u0002\u0002\u0002?#\u0003\u0002\u0002\u0002?\'\u0003\u0002\u0002",
+    "\u0002?1\u0003\u0002\u0002\u0002@Q\u0003\u0002\u0002\u0002AB\f\n\u0002",
+    "\u0002BC\t\u0003\u0002\u0002CP\u0005\u0004\u0003\u000bDE\f\t\u0002\u0002",
+    "EF\t\u0004\u0002\u0002FP\u0005\u0004\u0003\nGH\f\b\u0002\u0002HI\t\u0005",
     "\u0002\u0002IP\u0005\u0004\u0003\tJK\f\u0007\u0002\u0002KL\t\u0006\u0002",
     "\u0002LP\u0005\u0004\u0003\bMN\f\f\u0002\u0002NP\u0005\u0006\u0004\u0002",
     "OA\u0003\u0002\u0002\u0002OD\u0003\u0002\u0002\u0002OG\u0003\u0002\u0002",
@@ -68,65 +66,533 @@ var serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964",
     "\u0002\u0002[\r\u0003\u0002\u0002\u0002\b,8;?OQ"].join("");
 
 
-var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
+const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
 
-var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); });
+const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
 
-var sharedContextCache = new antlr4.PredictionContextCache();
+const sharedContextCache = new antlr4.PredictionContextCache();
 
-var literalNames = [ null, null, null, null, null, null, null, null, null, 
-                     "','", "':'", "'::'", "'$'", "'$$'", "'*'", "'('", 
-                     "')'", "'['", "']'", null, null, null, null, null, 
-                     "'.'", null, null, null, null, "'&'", "'&&'", "'&<'", 
-                     "'@@'", "'@>'", "'@'", "'!'", "'!!'", "'!='", "'^'", 
-                     "'='", "'=>'", "'>'", "'>='", "'>>'", "'#'", "'#='", 
-                     "'#>'", "'#>>'", "'##'", "'->'", "'->>'", "'-|-'", 
-                     "'<'", "'<='", "'<@'", "'<^'", "'<>'", "'<->'", "'<<'", 
-                     "'<<='", "'<?>'", "'-'", "'%'", "'|'", "'||'", "'||/'", 
-                     "'|/'", "'+'", "'?'", "'?&'", "'?#'", "'?-'", "'?|'", 
-                     "'/'", "'~'", "'~='", "'~>=~'", "'~>~'", "'~<=~'", 
-                     "'~<~'", "'~*'", "'~~'", "';'" ];
+export default class BaserowFormula extends antlr4.Parser {
 
-var symbolicNames = [ null, "BLOCK_COMMENT", "LINE_COMMENT", "WHITESPACE", 
-                      "TRUE", "FALSE", "FIELD", "FIELDBYID", "LOOKUP", "COMMA", 
-                      "COLON", "COLON_COLON", "DOLLAR", "DOLLAR_DOLLAR", 
-                      "STAR", "OPEN_PAREN", "CLOSE_PAREN", "OPEN_BRACKET", 
-                      "CLOSE_BRACKET", "BIT_STRING", "REGEX_STRING", "NUMERIC_LITERAL", 
-                      "INTEGER_LITERAL", "HEX_INTEGER_LITERAL", "DOT", "SINGLEQ_STRING_LITERAL", 
-                      "DOUBLEQ_STRING_LITERAL", "IDENTIFIER", "IDENTIFIER_UNICODE", 
-                      "AMP", "AMP_AMP", "AMP_LT", "AT_AT", "AT_GT", "AT_SIGN", 
-                      "BANG", "BANG_BANG", "BANG_EQUAL", "CARET", "EQUAL", 
-                      "EQUAL_GT", "GT", "GTE", "GT_GT", "HASH", "HASH_EQ", 
-                      "HASH_GT", "HASH_GT_GT", "HASH_HASH", "HYPHEN_GT", 
-                      "HYPHEN_GT_GT", "HYPHEN_PIPE_HYPHEN", "LT", "LTE", 
-                      "LT_AT", "LT_CARET", "LT_GT", "LT_HYPHEN_GT", "LT_LT", 
-                      "LT_LT_EQ", "LT_QMARK_GT", "MINUS", "PERCENT", "PIPE", 
-                      "PIPE_PIPE", "PIPE_PIPE_SLASH", "PIPE_SLASH", "PLUS", 
-                      "QMARK", "QMARK_AMP", "QMARK_HASH", "QMARK_HYPHEN", 
-                      "QMARK_PIPE", "SLASH", "TIL", "TIL_EQ", "TIL_GTE_TIL", 
-                      "TIL_GT_TIL", "TIL_LTE_TIL", "TIL_LT_TIL", "TIL_STAR", 
-                      "TIL_TIL", "SEMI", "ErrorCharacter" ];
+    static grammarFileName = "BaserowFormula.g4";
+    static literalNames = [ null, null, null, null, null, null, null, null, 
+                            null, "','", "':'", "'::'", "'$'", "'$$'", "'*'", 
+                            "'('", "')'", "'['", "']'", null, null, null, 
+                            null, null, "'.'", null, null, null, null, "'&'", 
+                            "'&&'", "'&<'", "'@@'", "'@>'", "'@'", "'!'", 
+                            "'!!'", "'!='", "'^'", "'='", "'=>'", "'>'", 
+                            "'>='", "'>>'", "'#'", "'#='", "'#>'", "'#>>'", 
+                            "'##'", "'->'", "'->>'", "'-|-'", "'<'", "'<='", 
+                            "'<@'", "'<^'", "'<>'", "'<->'", "'<<'", "'<<='", 
+                            "'<?>'", "'-'", "'%'", "'|'", "'||'", "'||/'", 
+                            "'|/'", "'+'", "'?'", "'?&'", "'?#'", "'?-'", 
+                            "'?|'", "'/'", "'~'", "'~='", "'~>=~'", "'~>~'", 
+                            "'~<=~'", "'~<~'", "'~*'", "'~~'", "';'" ];
+    static symbolicNames = [ null, "BLOCK_COMMENT", "LINE_COMMENT", "WHITESPACE", 
+                             "TRUE", "FALSE", "FIELD", "FIELDBYID", "LOOKUP", 
+                             "COMMA", "COLON", "COLON_COLON", "DOLLAR", 
+                             "DOLLAR_DOLLAR", "STAR", "OPEN_PAREN", "CLOSE_PAREN", 
+                             "OPEN_BRACKET", "CLOSE_BRACKET", "BIT_STRING", 
+                             "REGEX_STRING", "NUMERIC_LITERAL", "INTEGER_LITERAL", 
+                             "HEX_INTEGER_LITERAL", "DOT", "SINGLEQ_STRING_LITERAL", 
+                             "DOUBLEQ_STRING_LITERAL", "IDENTIFIER", "IDENTIFIER_UNICODE", 
+                             "AMP", "AMP_AMP", "AMP_LT", "AT_AT", "AT_GT", 
+                             "AT_SIGN", "BANG", "BANG_BANG", "BANG_EQUAL", 
+                             "CARET", "EQUAL", "EQUAL_GT", "GT", "GTE", 
+                             "GT_GT", "HASH", "HASH_EQ", "HASH_GT", "HASH_GT_GT", 
+                             "HASH_HASH", "HYPHEN_GT", "HYPHEN_GT_GT", "HYPHEN_PIPE_HYPHEN", 
+                             "LT", "LTE", "LT_AT", "LT_CARET", "LT_GT", 
+                             "LT_HYPHEN_GT", "LT_LT", "LT_LT_EQ", "LT_QMARK_GT", 
+                             "MINUS", "PERCENT", "PIPE", "PIPE_PIPE", "PIPE_PIPE_SLASH", 
+                             "PIPE_SLASH", "PLUS", "QMARK", "QMARK_AMP", 
+                             "QMARK_HASH", "QMARK_HYPHEN", "QMARK_PIPE", 
+                             "SLASH", "TIL", "TIL_EQ", "TIL_GTE_TIL", "TIL_GT_TIL", 
+                             "TIL_LTE_TIL", "TIL_LT_TIL", "TIL_STAR", "TIL_TIL", 
+                             "SEMI", "ErrorCharacter" ];
+    static ruleNames = [ "root", "expr", "ws_or_comment", "func_name", "field_reference", 
+                         "identifier" ];
 
-var ruleNames =  [ "root", "expr", "ws_or_comment", "func_name", "field_reference", 
-                   "identifier" ];
+    constructor(input) {
+        super(input);
+        this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache);
+        this.ruleNames = BaserowFormula.ruleNames;
+        this.literalNames = BaserowFormula.literalNames;
+        this.symbolicNames = BaserowFormula.symbolicNames;
+    }
 
-function BaserowFormula (input) {
-	antlr4.Parser.call(this, input);
-    this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache);
-    this.ruleNames = ruleNames;
-    this.literalNames = literalNames;
-    this.symbolicNames = symbolicNames;
-    return this;
-}
+    get atn() {
+        return atn;
+    }
 
-BaserowFormula.prototype = Object.create(antlr4.Parser.prototype);
-BaserowFormula.prototype.constructor = BaserowFormula;
+    sempred(localctx, ruleIndex, predIndex) {
+    	switch(ruleIndex) {
+    	case 1:
+    	    		return this.expr_sempred(localctx, predIndex);
+        default:
+            throw "No predicate with index:" + ruleIndex;
+       }
+    }
 
-Object.defineProperty(BaserowFormula.prototype, "atn", {
-	get : function() {
-		return atn;
+    expr_sempred(localctx, predIndex) {
+    	switch(predIndex) {
+    		case 0:
+    			return this.precpred(this._ctx, 8);
+    		case 1:
+    			return this.precpred(this._ctx, 7);
+    		case 2:
+    			return this.precpred(this._ctx, 6);
+    		case 3:
+    			return this.precpred(this._ctx, 5);
+    		case 4:
+    			return this.precpred(this._ctx, 10);
+    		default:
+    			throw "No predicate with index:" + predIndex;
+    	}
+    };
+
+
+
+
+	root() {
+	    let localctx = new RootContext(this, this._ctx, this.state);
+	    this.enterRule(localctx, 0, BaserowFormula.RULE_root);
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 12;
+	        this.expr(0);
+	        this.state = 13;
+	        this.match(BaserowFormula.EOF);
+	    } catch (re) {
+	    	if(re instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = re;
+		        this._errHandler.reportError(this, re);
+		        this._errHandler.recover(this, re);
+		    } else {
+		    	throw re;
+		    }
+	    } finally {
+	        this.exitRule();
+	    }
+	    return localctx;
 	}
-});
+
+
+	expr(_p) {
+		if(_p===undefined) {
+		    _p = 0;
+		}
+	    const _parentctx = this._ctx;
+	    const _parentState = this.state;
+	    let localctx = new ExprContext(this, this._ctx, _parentState);
+	    let _prevctx = localctx;
+	    const _startState = 2;
+	    this.enterRecursionRule(localctx, 2, BaserowFormula.RULE_expr, _p);
+	    var _la = 0; // Token type
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 61;
+	        this._errHandler.sync(this);
+	        switch(this._input.LA(1)) {
+	        case BaserowFormula.SINGLEQ_STRING_LITERAL:
+	            localctx = new StringLiteralContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+
+	            this.state = 16;
+	            this.match(BaserowFormula.SINGLEQ_STRING_LITERAL);
+	            break;
+	        case BaserowFormula.DOUBLEQ_STRING_LITERAL:
+	            localctx = new StringLiteralContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 17;
+	            this.match(BaserowFormula.DOUBLEQ_STRING_LITERAL);
+	            break;
+	        case BaserowFormula.INTEGER_LITERAL:
+	            localctx = new IntegerLiteralContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 18;
+	            this.match(BaserowFormula.INTEGER_LITERAL);
+	            break;
+	        case BaserowFormula.NUMERIC_LITERAL:
+	            localctx = new DecimalLiteralContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 19;
+	            this.match(BaserowFormula.NUMERIC_LITERAL);
+	            break;
+	        case BaserowFormula.TRUE:
+	        case BaserowFormula.FALSE:
+	            localctx = new BooleanLiteralContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 20;
+	            _la = this._input.LA(1);
+	            if(!(_la===BaserowFormula.TRUE || _la===BaserowFormula.FALSE)) {
+	            this._errHandler.recoverInline(this);
+	            }
+	            else {
+	            	this._errHandler.reportMatch(this);
+	                this.consume();
+	            }
+	            break;
+	        case BaserowFormula.BLOCK_COMMENT:
+	        case BaserowFormula.LINE_COMMENT:
+	        case BaserowFormula.WHITESPACE:
+	            localctx = new LeftWhitespaceOrCommentsContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 21;
+	            this.ws_or_comment();
+	            this.state = 22;
+	            this.expr(11);
+	            break;
+	        case BaserowFormula.OPEN_PAREN:
+	            localctx = new BracketsContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 24;
+	            this.match(BaserowFormula.OPEN_PAREN);
+	            this.state = 25;
+	            this.expr(0);
+	            this.state = 26;
+	            this.match(BaserowFormula.CLOSE_PAREN);
+	            break;
+	        case BaserowFormula.FIELD:
+	            localctx = new FieldReferenceContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 28;
+	            this.match(BaserowFormula.FIELD);
+	            this.state = 29;
+	            this.match(BaserowFormula.OPEN_PAREN);
+	            this.state = 30;
+	            this.field_reference();
+	            this.state = 31;
+	            this.match(BaserowFormula.CLOSE_PAREN);
+	            break;
+	        case BaserowFormula.FIELDBYID:
+	            localctx = new FieldByIdReferenceContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 33;
+	            this.match(BaserowFormula.FIELDBYID);
+	            this.state = 34;
+	            this.match(BaserowFormula.OPEN_PAREN);
+	            this.state = 35;
+	            this.match(BaserowFormula.INTEGER_LITERAL);
+	            this.state = 36;
+	            this.match(BaserowFormula.CLOSE_PAREN);
+	            break;
+	        case BaserowFormula.LOOKUP:
+	            localctx = new LookupFieldReferenceContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 37;
+	            this.match(BaserowFormula.LOOKUP);
+	            this.state = 38;
+	            this.match(BaserowFormula.OPEN_PAREN);
+	            this.state = 39;
+	            this.field_reference();
+	            this.state = 40;
+	            this.match(BaserowFormula.COMMA);
+	            this.state = 42;
+	            this._errHandler.sync(this);
+	            _la = this._input.LA(1);
+	            if(_la===BaserowFormula.WHITESPACE) {
+	                this.state = 41;
+	                this.match(BaserowFormula.WHITESPACE);
+	            }
+
+	            this.state = 44;
+	            this.field_reference();
+	            this.state = 45;
+	            this.match(BaserowFormula.CLOSE_PAREN);
+	            break;
+	        case BaserowFormula.IDENTIFIER:
+	        case BaserowFormula.IDENTIFIER_UNICODE:
+	            localctx = new FunctionCallContext(this, localctx);
+	            this._ctx = localctx;
+	            _prevctx = localctx;
+	            this.state = 47;
+	            this.func_name();
+	            this.state = 48;
+	            this.match(BaserowFormula.OPEN_PAREN);
+	            this.state = 57;
+	            this._errHandler.sync(this);
+	            _la = this._input.LA(1);
+	            if((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << BaserowFormula.BLOCK_COMMENT) | (1 << BaserowFormula.LINE_COMMENT) | (1 << BaserowFormula.WHITESPACE) | (1 << BaserowFormula.TRUE) | (1 << BaserowFormula.FALSE) | (1 << BaserowFormula.FIELD) | (1 << BaserowFormula.FIELDBYID) | (1 << BaserowFormula.LOOKUP) | (1 << BaserowFormula.OPEN_PAREN) | (1 << BaserowFormula.NUMERIC_LITERAL) | (1 << BaserowFormula.INTEGER_LITERAL) | (1 << BaserowFormula.SINGLEQ_STRING_LITERAL) | (1 << BaserowFormula.DOUBLEQ_STRING_LITERAL) | (1 << BaserowFormula.IDENTIFIER) | (1 << BaserowFormula.IDENTIFIER_UNICODE))) !== 0)) {
+	                this.state = 49;
+	                this.expr(0);
+	                this.state = 54;
+	                this._errHandler.sync(this);
+	                _la = this._input.LA(1);
+	                while(_la===BaserowFormula.COMMA) {
+	                    this.state = 50;
+	                    this.match(BaserowFormula.COMMA);
+	                    this.state = 51;
+	                    this.expr(0);
+	                    this.state = 56;
+	                    this._errHandler.sync(this);
+	                    _la = this._input.LA(1);
+	                }
+	            }
+
+	            this.state = 59;
+	            this.match(BaserowFormula.CLOSE_PAREN);
+	            break;
+	        default:
+	            throw new antlr4.error.NoViableAltException(this);
+	        }
+	        this._ctx.stop = this._input.LT(-1);
+	        this.state = 79;
+	        this._errHandler.sync(this);
+	        let _alt = this._interp.adaptivePredict(this._input,5,this._ctx)
+	        while(_alt!=2 && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
+	            if(_alt===1) {
+	                if(this._parseListeners!==null) {
+	                    this.triggerExitRuleEvent();
+	                }
+	                _prevctx = localctx;
+	                this.state = 77;
+	                this._errHandler.sync(this);
+	                var la_ = this._interp.adaptivePredict(this._input,4,this._ctx);
+	                switch(la_) {
+	                case 1:
+	                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
+	                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
+	                    this.state = 63;
+	                    if (!( this.precpred(this._ctx, 8))) {
+	                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 8)");
+	                    }
+	                    this.state = 64;
+	                    localctx.op = this._input.LT(1);
+	                    _la = this._input.LA(1);
+	                    if(!(_la===BaserowFormula.STAR || _la===BaserowFormula.SLASH)) {
+	                        localctx.op = this._errHandler.recoverInline(this);
+	                    }
+	                    else {
+	                    	this._errHandler.reportMatch(this);
+	                        this.consume();
+	                    }
+	                    this.state = 65;
+	                    this.expr(9);
+	                    break;
+
+	                case 2:
+	                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
+	                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
+	                    this.state = 66;
+	                    if (!( this.precpred(this._ctx, 7))) {
+	                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 7)");
+	                    }
+	                    this.state = 67;
+	                    localctx.op = this._input.LT(1);
+	                    _la = this._input.LA(1);
+	                    if(!(_la===BaserowFormula.MINUS || _la===BaserowFormula.PLUS)) {
+	                        localctx.op = this._errHandler.recoverInline(this);
+	                    }
+	                    else {
+	                    	this._errHandler.reportMatch(this);
+	                        this.consume();
+	                    }
+	                    this.state = 68;
+	                    this.expr(8);
+	                    break;
+
+	                case 3:
+	                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
+	                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
+	                    this.state = 69;
+	                    if (!( this.precpred(this._ctx, 6))) {
+	                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 6)");
+	                    }
+	                    this.state = 70;
+	                    localctx.op = this._input.LT(1);
+	                    _la = this._input.LA(1);
+	                    if(!(((((_la - 41)) & ~0x1f) == 0 && ((1 << (_la - 41)) & ((1 << (BaserowFormula.GT - 41)) | (1 << (BaserowFormula.GTE - 41)) | (1 << (BaserowFormula.LT - 41)) | (1 << (BaserowFormula.LTE - 41)))) !== 0))) {
+	                        localctx.op = this._errHandler.recoverInline(this);
+	                    }
+	                    else {
+	                    	this._errHandler.reportMatch(this);
+	                        this.consume();
+	                    }
+	                    this.state = 71;
+	                    this.expr(7);
+	                    break;
+
+	                case 4:
+	                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
+	                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
+	                    this.state = 72;
+	                    if (!( this.precpred(this._ctx, 5))) {
+	                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 5)");
+	                    }
+	                    this.state = 73;
+	                    localctx.op = this._input.LT(1);
+	                    _la = this._input.LA(1);
+	                    if(!(_la===BaserowFormula.BANG_EQUAL || _la===BaserowFormula.EQUAL)) {
+	                        localctx.op = this._errHandler.recoverInline(this);
+	                    }
+	                    else {
+	                    	this._errHandler.reportMatch(this);
+	                        this.consume();
+	                    }
+	                    this.state = 74;
+	                    this.expr(6);
+	                    break;
+
+	                case 5:
+	                    localctx = new RightWhitespaceOrCommentsContext(this, new ExprContext(this, _parentctx, _parentState));
+	                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
+	                    this.state = 75;
+	                    if (!( this.precpred(this._ctx, 10))) {
+	                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 10)");
+	                    }
+	                    this.state = 76;
+	                    this.ws_or_comment();
+	                    break;
+
+	                } 
+	            }
+	            this.state = 81;
+	            this._errHandler.sync(this);
+	            _alt = this._interp.adaptivePredict(this._input,5,this._ctx);
+	        }
+
+	    } catch( error) {
+	        if(error instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = error;
+		        this._errHandler.reportError(this, error);
+		        this._errHandler.recover(this, error);
+		    } else {
+		    	throw error;
+		    }
+	    } finally {
+	        this.unrollRecursionContexts(_parentctx)
+	    }
+	    return localctx;
+	}
+
+
+
+	ws_or_comment() {
+	    let localctx = new Ws_or_commentContext(this, this._ctx, this.state);
+	    this.enterRule(localctx, 4, BaserowFormula.RULE_ws_or_comment);
+	    var _la = 0; // Token type
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 82;
+	        _la = this._input.LA(1);
+	        if(!((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << BaserowFormula.BLOCK_COMMENT) | (1 << BaserowFormula.LINE_COMMENT) | (1 << BaserowFormula.WHITESPACE))) !== 0))) {
+	        this._errHandler.recoverInline(this);
+	        }
+	        else {
+	        	this._errHandler.reportMatch(this);
+	            this.consume();
+	        }
+	    } catch (re) {
+	    	if(re instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = re;
+		        this._errHandler.reportError(this, re);
+		        this._errHandler.recover(this, re);
+		    } else {
+		    	throw re;
+		    }
+	    } finally {
+	        this.exitRule();
+	    }
+	    return localctx;
+	}
+
+
+
+	func_name() {
+	    let localctx = new Func_nameContext(this, this._ctx, this.state);
+	    this.enterRule(localctx, 6, BaserowFormula.RULE_func_name);
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 84;
+	        this.identifier();
+	    } catch (re) {
+	    	if(re instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = re;
+		        this._errHandler.reportError(this, re);
+		        this._errHandler.recover(this, re);
+		    } else {
+		    	throw re;
+		    }
+	    } finally {
+	        this.exitRule();
+	    }
+	    return localctx;
+	}
+
+
+
+	field_reference() {
+	    let localctx = new Field_referenceContext(this, this._ctx, this.state);
+	    this.enterRule(localctx, 8, BaserowFormula.RULE_field_reference);
+	    var _la = 0; // Token type
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 86;
+	        _la = this._input.LA(1);
+	        if(!(_la===BaserowFormula.SINGLEQ_STRING_LITERAL || _la===BaserowFormula.DOUBLEQ_STRING_LITERAL)) {
+	        this._errHandler.recoverInline(this);
+	        }
+	        else {
+	        	this._errHandler.reportMatch(this);
+	            this.consume();
+	        }
+	    } catch (re) {
+	    	if(re instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = re;
+		        this._errHandler.reportError(this, re);
+		        this._errHandler.recover(this, re);
+		    } else {
+		    	throw re;
+		    }
+	    } finally {
+	        this.exitRule();
+	    }
+	    return localctx;
+	}
+
+
+
+	identifier() {
+	    let localctx = new IdentifierContext(this, this._ctx, this.state);
+	    this.enterRule(localctx, 10, BaserowFormula.RULE_identifier);
+	    var _la = 0; // Token type
+	    try {
+	        this.enterOuterAlt(localctx, 1);
+	        this.state = 88;
+	        _la = this._input.LA(1);
+	        if(!(_la===BaserowFormula.IDENTIFIER || _la===BaserowFormula.IDENTIFIER_UNICODE)) {
+	        this._errHandler.recoverInline(this);
+	        }
+	        else {
+	        	this._errHandler.reportMatch(this);
+	            this.consume();
+	        }
+	    } catch (re) {
+	    	if(re instanceof antlr4.error.RecognitionException) {
+		        localctx.exception = re;
+		        this._errHandler.reportError(this, re);
+		        this._errHandler.recover(this, re);
+		    } else {
+		    	throw re;
+		    }
+	    } finally {
+	        this.exitRule();
+	    }
+	    return localctx;
+	}
+
+
+}
 
 BaserowFormula.EOF = antlr4.Token.EOF;
 BaserowFormula.BLOCK_COMMENT = 1;
@@ -220,1314 +686,854 @@ BaserowFormula.RULE_func_name = 3;
 BaserowFormula.RULE_field_reference = 4;
 BaserowFormula.RULE_identifier = 5;
 
+class RootContext extends antlr4.ParserRuleContext {
 
-function RootContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_root;
-    return this;
-}
-
-RootContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-RootContext.prototype.constructor = RootContext;
-
-RootContext.prototype.expr = function() {
-    return this.getTypedRuleContext(ExprContext,0);
-};
-
-RootContext.prototype.EOF = function() {
-    return this.getToken(BaserowFormula.EOF, 0);
-};
-
-RootContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterRoot(this);
-	}
-};
-
-RootContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitRoot(this);
-	}
-};
-
-RootContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitRoot(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
+        }
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
+        }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_root;
     }
-};
 
+	expr() {
+	    return this.getTypedRuleContext(ExprContext,0);
+	};
 
+	EOF() {
+	    return this.getToken(BaserowFormula.EOF, 0);
+	};
 
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterRoot(this);
+		}
+	}
 
-BaserowFormula.RootContext = RootContext;
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitRoot(this);
+		}
+	}
 
-BaserowFormula.prototype.root = function() {
-
-    var localctx = new RootContext(this, this._ctx, this.state);
-    this.enterRule(localctx, 0, BaserowFormula.RULE_root);
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 12;
-        this.expr(0);
-        this.state = 13;
-        this.match(BaserowFormula.EOF);
-    } catch (re) {
-    	if(re instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = re;
-	        this._errHandler.reportError(this, re);
-	        this._errHandler.recover(this, re);
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitRoot(this);
 	    } else {
-	    	throw re;
+	        return visitor.visitChildren(this);
 	    }
-    } finally {
-        this.exitRule();
+	}
+
+
+}
+
+
+
+class ExprContext extends antlr4.ParserRuleContext {
+
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
+        }
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
+        }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_expr;
     }
-    return localctx;
-};
 
 
-function ExprContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_expr;
-    return this;
+	 
+		copyFrom(ctx) {
+			super.copyFrom(ctx);
+		}
+
 }
 
-ExprContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-ExprContext.prototype.constructor = ExprContext;
+
+class FieldReferenceContext extends ExprContext {
+
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
+    }
+
+	FIELD() {
+	    return this.getToken(BaserowFormula.FIELD, 0);
+	};
+
+	OPEN_PAREN() {
+	    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
+	};
+
+	field_reference() {
+	    return this.getTypedRuleContext(Field_referenceContext,0);
+	};
+
+	CLOSE_PAREN() {
+	    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterFieldReference(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitFieldReference(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitFieldReference(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
- 
-ExprContext.prototype.copyFrom = function(ctx) {
-    antlr4.ParserRuleContext.prototype.copyFrom.call(this, ctx);
-};
-
-function FieldReferenceContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-FieldReferenceContext.prototype = Object.create(ExprContext.prototype);
-FieldReferenceContext.prototype.constructor = FieldReferenceContext;
-
 BaserowFormula.FieldReferenceContext = FieldReferenceContext;
 
-FieldReferenceContext.prototype.FIELD = function() {
-    return this.getToken(BaserowFormula.FIELD, 0);
-};
+class StringLiteralContext extends ExprContext {
 
-FieldReferenceContext.prototype.OPEN_PAREN = function() {
-    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
-};
-
-FieldReferenceContext.prototype.field_reference = function() {
-    return this.getTypedRuleContext(Field_referenceContext,0);
-};
-
-FieldReferenceContext.prototype.CLOSE_PAREN = function() {
-    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
-};
-FieldReferenceContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterFieldReference(this);
-	}
-};
-
-FieldReferenceContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitFieldReference(this);
-	}
-};
-
-FieldReferenceContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitFieldReference(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	SINGLEQ_STRING_LITERAL() {
+	    return this.getToken(BaserowFormula.SINGLEQ_STRING_LITERAL, 0);
+	};
+
+	DOUBLEQ_STRING_LITERAL() {
+	    return this.getToken(BaserowFormula.DOUBLEQ_STRING_LITERAL, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterStringLiteral(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitStringLiteral(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitStringLiteral(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function StringLiteralContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-StringLiteralContext.prototype = Object.create(ExprContext.prototype);
-StringLiteralContext.prototype.constructor = StringLiteralContext;
-
 BaserowFormula.StringLiteralContext = StringLiteralContext;
 
-StringLiteralContext.prototype.SINGLEQ_STRING_LITERAL = function() {
-    return this.getToken(BaserowFormula.SINGLEQ_STRING_LITERAL, 0);
-};
+class BracketsContext extends ExprContext {
 
-StringLiteralContext.prototype.DOUBLEQ_STRING_LITERAL = function() {
-    return this.getToken(BaserowFormula.DOUBLEQ_STRING_LITERAL, 0);
-};
-StringLiteralContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterStringLiteral(this);
-	}
-};
-
-StringLiteralContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitStringLiteral(this);
-	}
-};
-
-StringLiteralContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitStringLiteral(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	OPEN_PAREN() {
+	    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
+	};
+
+	expr() {
+	    return this.getTypedRuleContext(ExprContext,0);
+	};
+
+	CLOSE_PAREN() {
+	    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterBrackets(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitBrackets(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitBrackets(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function BracketsContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-BracketsContext.prototype = Object.create(ExprContext.prototype);
-BracketsContext.prototype.constructor = BracketsContext;
-
 BaserowFormula.BracketsContext = BracketsContext;
 
-BracketsContext.prototype.OPEN_PAREN = function() {
-    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
-};
+class BooleanLiteralContext extends ExprContext {
 
-BracketsContext.prototype.expr = function() {
-    return this.getTypedRuleContext(ExprContext,0);
-};
-
-BracketsContext.prototype.CLOSE_PAREN = function() {
-    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
-};
-BracketsContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterBrackets(this);
-	}
-};
-
-BracketsContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitBrackets(this);
-	}
-};
-
-BracketsContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitBrackets(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	TRUE() {
+	    return this.getToken(BaserowFormula.TRUE, 0);
+	};
+
+	FALSE() {
+	    return this.getToken(BaserowFormula.FALSE, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterBooleanLiteral(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitBooleanLiteral(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitBooleanLiteral(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function BooleanLiteralContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-BooleanLiteralContext.prototype = Object.create(ExprContext.prototype);
-BooleanLiteralContext.prototype.constructor = BooleanLiteralContext;
-
 BaserowFormula.BooleanLiteralContext = BooleanLiteralContext;
 
-BooleanLiteralContext.prototype.TRUE = function() {
-    return this.getToken(BaserowFormula.TRUE, 0);
-};
+class RightWhitespaceOrCommentsContext extends ExprContext {
 
-BooleanLiteralContext.prototype.FALSE = function() {
-    return this.getToken(BaserowFormula.FALSE, 0);
-};
-BooleanLiteralContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterBooleanLiteral(this);
-	}
-};
-
-BooleanLiteralContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitBooleanLiteral(this);
-	}
-};
-
-BooleanLiteralContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitBooleanLiteral(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	expr() {
+	    return this.getTypedRuleContext(ExprContext,0);
+	};
+
+	ws_or_comment() {
+	    return this.getTypedRuleContext(Ws_or_commentContext,0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterRightWhitespaceOrComments(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitRightWhitespaceOrComments(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitRightWhitespaceOrComments(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function RightWhitespaceOrCommentsContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-RightWhitespaceOrCommentsContext.prototype = Object.create(ExprContext.prototype);
-RightWhitespaceOrCommentsContext.prototype.constructor = RightWhitespaceOrCommentsContext;
-
 BaserowFormula.RightWhitespaceOrCommentsContext = RightWhitespaceOrCommentsContext;
 
-RightWhitespaceOrCommentsContext.prototype.expr = function() {
-    return this.getTypedRuleContext(ExprContext,0);
-};
+class DecimalLiteralContext extends ExprContext {
 
-RightWhitespaceOrCommentsContext.prototype.ws_or_comment = function() {
-    return this.getTypedRuleContext(Ws_or_commentContext,0);
-};
-RightWhitespaceOrCommentsContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterRightWhitespaceOrComments(this);
-	}
-};
-
-RightWhitespaceOrCommentsContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitRightWhitespaceOrComments(this);
-	}
-};
-
-RightWhitespaceOrCommentsContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitRightWhitespaceOrComments(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	NUMERIC_LITERAL() {
+	    return this.getToken(BaserowFormula.NUMERIC_LITERAL, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterDecimalLiteral(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitDecimalLiteral(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitDecimalLiteral(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function DecimalLiteralContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-DecimalLiteralContext.prototype = Object.create(ExprContext.prototype);
-DecimalLiteralContext.prototype.constructor = DecimalLiteralContext;
-
 BaserowFormula.DecimalLiteralContext = DecimalLiteralContext;
 
-DecimalLiteralContext.prototype.NUMERIC_LITERAL = function() {
-    return this.getToken(BaserowFormula.NUMERIC_LITERAL, 0);
-};
-DecimalLiteralContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterDecimalLiteral(this);
-	}
-};
+class LeftWhitespaceOrCommentsContext extends ExprContext {
 
-DecimalLiteralContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitDecimalLiteral(this);
-	}
-};
-
-DecimalLiteralContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitDecimalLiteral(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	ws_or_comment() {
+	    return this.getTypedRuleContext(Ws_or_commentContext,0);
+	};
+
+	expr() {
+	    return this.getTypedRuleContext(ExprContext,0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterLeftWhitespaceOrComments(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitLeftWhitespaceOrComments(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitLeftWhitespaceOrComments(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function LeftWhitespaceOrCommentsContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-LeftWhitespaceOrCommentsContext.prototype = Object.create(ExprContext.prototype);
-LeftWhitespaceOrCommentsContext.prototype.constructor = LeftWhitespaceOrCommentsContext;
-
 BaserowFormula.LeftWhitespaceOrCommentsContext = LeftWhitespaceOrCommentsContext;
 
-LeftWhitespaceOrCommentsContext.prototype.ws_or_comment = function() {
-    return this.getTypedRuleContext(Ws_or_commentContext,0);
-};
+class FunctionCallContext extends ExprContext {
 
-LeftWhitespaceOrCommentsContext.prototype.expr = function() {
-    return this.getTypedRuleContext(ExprContext,0);
-};
-LeftWhitespaceOrCommentsContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterLeftWhitespaceOrComments(this);
-	}
-};
-
-LeftWhitespaceOrCommentsContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitLeftWhitespaceOrComments(this);
-	}
-};
-
-LeftWhitespaceOrCommentsContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitLeftWhitespaceOrComments(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	func_name() {
+	    return this.getTypedRuleContext(Func_nameContext,0);
+	};
+
+	OPEN_PAREN() {
+	    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
+	};
+
+	CLOSE_PAREN() {
+	    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
+	};
+
+	expr = function(i) {
+	    if(i===undefined) {
+	        i = null;
+	    }
+	    if(i===null) {
+	        return this.getTypedRuleContexts(ExprContext);
+	    } else {
+	        return this.getTypedRuleContext(ExprContext,i);
+	    }
+	};
+
+	COMMA = function(i) {
+		if(i===undefined) {
+			i = null;
+		}
+	    if(i===null) {
+	        return this.getTokens(BaserowFormula.COMMA);
+	    } else {
+	        return this.getToken(BaserowFormula.COMMA, i);
+	    }
+	};
+
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterFunctionCall(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitFunctionCall(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitFunctionCall(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function FunctionCallContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-FunctionCallContext.prototype = Object.create(ExprContext.prototype);
-FunctionCallContext.prototype.constructor = FunctionCallContext;
-
 BaserowFormula.FunctionCallContext = FunctionCallContext;
 
-FunctionCallContext.prototype.func_name = function() {
-    return this.getTypedRuleContext(Func_nameContext,0);
-};
+class FieldByIdReferenceContext extends ExprContext {
 
-FunctionCallContext.prototype.OPEN_PAREN = function() {
-    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
-};
-
-FunctionCallContext.prototype.CLOSE_PAREN = function() {
-    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
-};
-
-FunctionCallContext.prototype.expr = function(i) {
-    if(i===undefined) {
-        i = null;
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-    if(i===null) {
-        return this.getTypedRuleContexts(ExprContext);
-    } else {
-        return this.getTypedRuleContext(ExprContext,i);
-    }
-};
 
-FunctionCallContext.prototype.COMMA = function(i) {
-	if(i===undefined) {
-		i = null;
+	FIELDBYID() {
+	    return this.getToken(BaserowFormula.FIELDBYID, 0);
+	};
+
+	OPEN_PAREN() {
+	    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
+	};
+
+	INTEGER_LITERAL() {
+	    return this.getToken(BaserowFormula.INTEGER_LITERAL, 0);
+	};
+
+	CLOSE_PAREN() {
+	    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterFieldByIdReference(this);
+		}
 	}
-    if(i===null) {
-        return this.getTokens(BaserowFormula.COMMA);
-    } else {
-        return this.getToken(BaserowFormula.COMMA, i);
-    }
-};
 
-FunctionCallContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterFunctionCall(this);
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitFieldByIdReference(this);
+		}
 	}
-};
 
-FunctionCallContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitFunctionCall(this);
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitFieldByIdReference(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
 	}
-};
-
-FunctionCallContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitFunctionCall(this);
-    } else {
-        return visitor.visitChildren(this);
-    }
-};
 
 
-function FieldByIdReferenceContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-FieldByIdReferenceContext.prototype = Object.create(ExprContext.prototype);
-FieldByIdReferenceContext.prototype.constructor = FieldByIdReferenceContext;
-
 BaserowFormula.FieldByIdReferenceContext = FieldByIdReferenceContext;
 
-FieldByIdReferenceContext.prototype.FIELDBYID = function() {
-    return this.getToken(BaserowFormula.FIELDBYID, 0);
-};
+class LookupFieldReferenceContext extends ExprContext {
 
-FieldByIdReferenceContext.prototype.OPEN_PAREN = function() {
-    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
-};
-
-FieldByIdReferenceContext.prototype.INTEGER_LITERAL = function() {
-    return this.getToken(BaserowFormula.INTEGER_LITERAL, 0);
-};
-
-FieldByIdReferenceContext.prototype.CLOSE_PAREN = function() {
-    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
-};
-FieldByIdReferenceContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterFieldByIdReference(this);
-	}
-};
-
-FieldByIdReferenceContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitFieldByIdReference(this);
-	}
-};
-
-FieldByIdReferenceContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitFieldByIdReference(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-};
+
+	LOOKUP() {
+	    return this.getToken(BaserowFormula.LOOKUP, 0);
+	};
+
+	OPEN_PAREN() {
+	    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
+	};
+
+	field_reference = function(i) {
+	    if(i===undefined) {
+	        i = null;
+	    }
+	    if(i===null) {
+	        return this.getTypedRuleContexts(Field_referenceContext);
+	    } else {
+	        return this.getTypedRuleContext(Field_referenceContext,i);
+	    }
+	};
+
+	COMMA() {
+	    return this.getToken(BaserowFormula.COMMA, 0);
+	};
+
+	CLOSE_PAREN() {
+	    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
+	};
+
+	WHITESPACE() {
+	    return this.getToken(BaserowFormula.WHITESPACE, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterLookupFieldReference(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitLookupFieldReference(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitLookupFieldReference(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function LookupFieldReferenceContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-LookupFieldReferenceContext.prototype = Object.create(ExprContext.prototype);
-LookupFieldReferenceContext.prototype.constructor = LookupFieldReferenceContext;
-
 BaserowFormula.LookupFieldReferenceContext = LookupFieldReferenceContext;
 
-LookupFieldReferenceContext.prototype.LOOKUP = function() {
-    return this.getToken(BaserowFormula.LOOKUP, 0);
-};
+class IntegerLiteralContext extends ExprContext {
 
-LookupFieldReferenceContext.prototype.OPEN_PAREN = function() {
-    return this.getToken(BaserowFormula.OPEN_PAREN, 0);
-};
-
-LookupFieldReferenceContext.prototype.field_reference = function(i) {
-    if(i===undefined) {
-        i = null;
+    constructor(parser, ctx) {
+        super(parser);
+        super.copyFrom(ctx);
     }
-    if(i===null) {
-        return this.getTypedRuleContexts(Field_referenceContext);
-    } else {
-        return this.getTypedRuleContext(Field_referenceContext,i);
-    }
-};
 
-LookupFieldReferenceContext.prototype.COMMA = function() {
-    return this.getToken(BaserowFormula.COMMA, 0);
-};
+	INTEGER_LITERAL() {
+	    return this.getToken(BaserowFormula.INTEGER_LITERAL, 0);
+	};
 
-LookupFieldReferenceContext.prototype.CLOSE_PAREN = function() {
-    return this.getToken(BaserowFormula.CLOSE_PAREN, 0);
-};
-
-LookupFieldReferenceContext.prototype.WHITESPACE = function() {
-    return this.getToken(BaserowFormula.WHITESPACE, 0);
-};
-LookupFieldReferenceContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterLookupFieldReference(this);
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterIntegerLiteral(this);
+		}
 	}
-};
 
-LookupFieldReferenceContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitLookupFieldReference(this);
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitIntegerLiteral(this);
+		}
 	}
-};
 
-LookupFieldReferenceContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitLookupFieldReference(this);
-    } else {
-        return visitor.visitChildren(this);
-    }
-};
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitIntegerLiteral(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function IntegerLiteralContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-IntegerLiteralContext.prototype = Object.create(ExprContext.prototype);
-IntegerLiteralContext.prototype.constructor = IntegerLiteralContext;
-
 BaserowFormula.IntegerLiteralContext = IntegerLiteralContext;
 
-IntegerLiteralContext.prototype.INTEGER_LITERAL = function() {
-    return this.getToken(BaserowFormula.INTEGER_LITERAL, 0);
-};
-IntegerLiteralContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterIntegerLiteral(this);
-	}
-};
+class BinaryOpContext extends ExprContext {
 
-IntegerLiteralContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitIntegerLiteral(this);
-	}
-};
-
-IntegerLiteralContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitIntegerLiteral(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, ctx) {
+        super(parser);
+        this.op = null; // Token;
+        super.copyFrom(ctx);
     }
-};
+
+	expr = function(i) {
+	    if(i===undefined) {
+	        i = null;
+	    }
+	    if(i===null) {
+	        return this.getTypedRuleContexts(ExprContext);
+	    } else {
+	        return this.getTypedRuleContext(ExprContext,i);
+	    }
+	};
+
+	SLASH() {
+	    return this.getToken(BaserowFormula.SLASH, 0);
+	};
+
+	STAR() {
+	    return this.getToken(BaserowFormula.STAR, 0);
+	};
+
+	PLUS() {
+	    return this.getToken(BaserowFormula.PLUS, 0);
+	};
+
+	MINUS() {
+	    return this.getToken(BaserowFormula.MINUS, 0);
+	};
+
+	GT() {
+	    return this.getToken(BaserowFormula.GT, 0);
+	};
+
+	LT() {
+	    return this.getToken(BaserowFormula.LT, 0);
+	};
+
+	GTE() {
+	    return this.getToken(BaserowFormula.GTE, 0);
+	};
+
+	LTE() {
+	    return this.getToken(BaserowFormula.LTE, 0);
+	};
+
+	EQUAL() {
+	    return this.getToken(BaserowFormula.EQUAL, 0);
+	};
+
+	BANG_EQUAL() {
+	    return this.getToken(BaserowFormula.BANG_EQUAL, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterBinaryOp(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitBinaryOp(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitBinaryOp(this);
+	    } else {
+	        return visitor.visitChildren(this);
+	    }
+	}
 
 
-function BinaryOpContext(parser, ctx) {
-	ExprContext.call(this, parser);
-    this.op = null; // Token;
-    ExprContext.prototype.copyFrom.call(this, ctx);
-    return this;
 }
 
-BinaryOpContext.prototype = Object.create(ExprContext.prototype);
-BinaryOpContext.prototype.constructor = BinaryOpContext;
-
 BaserowFormula.BinaryOpContext = BinaryOpContext;
 
-BinaryOpContext.prototype.expr = function(i) {
-    if(i===undefined) {
-        i = null;
-    }
-    if(i===null) {
-        return this.getTypedRuleContexts(ExprContext);
-    } else {
-        return this.getTypedRuleContext(ExprContext,i);
-    }
-};
+class Ws_or_commentContext extends antlr4.ParserRuleContext {
 
-BinaryOpContext.prototype.SLASH = function() {
-    return this.getToken(BaserowFormula.SLASH, 0);
-};
-
-BinaryOpContext.prototype.STAR = function() {
-    return this.getToken(BaserowFormula.STAR, 0);
-};
-
-BinaryOpContext.prototype.PLUS = function() {
-    return this.getToken(BaserowFormula.PLUS, 0);
-};
-
-BinaryOpContext.prototype.MINUS = function() {
-    return this.getToken(BaserowFormula.MINUS, 0);
-};
-
-BinaryOpContext.prototype.GT = function() {
-    return this.getToken(BaserowFormula.GT, 0);
-};
-
-BinaryOpContext.prototype.LT = function() {
-    return this.getToken(BaserowFormula.LT, 0);
-};
-
-BinaryOpContext.prototype.GTE = function() {
-    return this.getToken(BaserowFormula.GTE, 0);
-};
-
-BinaryOpContext.prototype.LTE = function() {
-    return this.getToken(BaserowFormula.LTE, 0);
-};
-
-BinaryOpContext.prototype.EQUAL = function() {
-    return this.getToken(BaserowFormula.EQUAL, 0);
-};
-
-BinaryOpContext.prototype.BANG_EQUAL = function() {
-    return this.getToken(BaserowFormula.BANG_EQUAL, 0);
-};
-BinaryOpContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterBinaryOp(this);
-	}
-};
-
-BinaryOpContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitBinaryOp(this);
-	}
-};
-
-BinaryOpContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitBinaryOp(this);
-    } else {
-        return visitor.visitChildren(this);
-    }
-};
-
-
-
-BaserowFormula.prototype.expr = function(_p) {
-	if(_p===undefined) {
-	    _p = 0;
-	}
-    var _parentctx = this._ctx;
-    var _parentState = this.state;
-    var localctx = new ExprContext(this, this._ctx, _parentState);
-    var _prevctx = localctx;
-    var _startState = 2;
-    this.enterRecursionRule(localctx, 2, BaserowFormula.RULE_expr, _p);
-    var _la = 0; // Token type
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 61;
-        this._errHandler.sync(this);
-        switch(this._input.LA(1)) {
-        case BaserowFormula.SINGLEQ_STRING_LITERAL:
-            localctx = new StringLiteralContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-
-            this.state = 16;
-            this.match(BaserowFormula.SINGLEQ_STRING_LITERAL);
-            break;
-        case BaserowFormula.DOUBLEQ_STRING_LITERAL:
-            localctx = new StringLiteralContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 17;
-            this.match(BaserowFormula.DOUBLEQ_STRING_LITERAL);
-            break;
-        case BaserowFormula.INTEGER_LITERAL:
-            localctx = new IntegerLiteralContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 18;
-            this.match(BaserowFormula.INTEGER_LITERAL);
-            break;
-        case BaserowFormula.NUMERIC_LITERAL:
-            localctx = new DecimalLiteralContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 19;
-            this.match(BaserowFormula.NUMERIC_LITERAL);
-            break;
-        case BaserowFormula.TRUE:
-        case BaserowFormula.FALSE:
-            localctx = new BooleanLiteralContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 20;
-            _la = this._input.LA(1);
-            if(!(_la===BaserowFormula.TRUE || _la===BaserowFormula.FALSE)) {
-            this._errHandler.recoverInline(this);
-            }
-            else {
-            	this._errHandler.reportMatch(this);
-                this.consume();
-            }
-            break;
-        case BaserowFormula.BLOCK_COMMENT:
-        case BaserowFormula.LINE_COMMENT:
-        case BaserowFormula.WHITESPACE:
-            localctx = new LeftWhitespaceOrCommentsContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 21;
-            this.ws_or_comment();
-            this.state = 22;
-            this.expr(11);
-            break;
-        case BaserowFormula.OPEN_PAREN:
-            localctx = new BracketsContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 24;
-            this.match(BaserowFormula.OPEN_PAREN);
-            this.state = 25;
-            this.expr(0);
-            this.state = 26;
-            this.match(BaserowFormula.CLOSE_PAREN);
-            break;
-        case BaserowFormula.FIELD:
-            localctx = new FieldReferenceContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 28;
-            this.match(BaserowFormula.FIELD);
-            this.state = 29;
-            this.match(BaserowFormula.OPEN_PAREN);
-            this.state = 30;
-            this.field_reference();
-            this.state = 31;
-            this.match(BaserowFormula.CLOSE_PAREN);
-            break;
-        case BaserowFormula.FIELDBYID:
-            localctx = new FieldByIdReferenceContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 33;
-            this.match(BaserowFormula.FIELDBYID);
-            this.state = 34;
-            this.match(BaserowFormula.OPEN_PAREN);
-            this.state = 35;
-            this.match(BaserowFormula.INTEGER_LITERAL);
-            this.state = 36;
-            this.match(BaserowFormula.CLOSE_PAREN);
-            break;
-        case BaserowFormula.LOOKUP:
-            localctx = new LookupFieldReferenceContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 37;
-            this.match(BaserowFormula.LOOKUP);
-            this.state = 38;
-            this.match(BaserowFormula.OPEN_PAREN);
-            this.state = 39;
-            this.field_reference();
-            this.state = 40;
-            this.match(BaserowFormula.COMMA);
-            this.state = 42;
-            this._errHandler.sync(this);
-            _la = this._input.LA(1);
-            if(_la===BaserowFormula.WHITESPACE) {
-                this.state = 41;
-                this.match(BaserowFormula.WHITESPACE);
-            }
-
-            this.state = 44;
-            this.field_reference();
-            this.state = 45;
-            this.match(BaserowFormula.CLOSE_PAREN);
-            break;
-        case BaserowFormula.IDENTIFIER:
-        case BaserowFormula.IDENTIFIER_UNICODE:
-            localctx = new FunctionCallContext(this, localctx);
-            this._ctx = localctx;
-            _prevctx = localctx;
-            this.state = 47;
-            this.func_name();
-            this.state = 48;
-            this.match(BaserowFormula.OPEN_PAREN);
-            this.state = 57;
-            this._errHandler.sync(this);
-            _la = this._input.LA(1);
-            if((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << BaserowFormula.BLOCK_COMMENT) | (1 << BaserowFormula.LINE_COMMENT) | (1 << BaserowFormula.WHITESPACE) | (1 << BaserowFormula.TRUE) | (1 << BaserowFormula.FALSE) | (1 << BaserowFormula.FIELD) | (1 << BaserowFormula.FIELDBYID) | (1 << BaserowFormula.LOOKUP) | (1 << BaserowFormula.OPEN_PAREN) | (1 << BaserowFormula.NUMERIC_LITERAL) | (1 << BaserowFormula.INTEGER_LITERAL) | (1 << BaserowFormula.SINGLEQ_STRING_LITERAL) | (1 << BaserowFormula.DOUBLEQ_STRING_LITERAL) | (1 << BaserowFormula.IDENTIFIER) | (1 << BaserowFormula.IDENTIFIER_UNICODE))) !== 0)) {
-                this.state = 49;
-                this.expr(0);
-                this.state = 54;
-                this._errHandler.sync(this);
-                _la = this._input.LA(1);
-                while(_la===BaserowFormula.COMMA) {
-                    this.state = 50;
-                    this.match(BaserowFormula.COMMA);
-                    this.state = 51;
-                    this.expr(0);
-                    this.state = 56;
-                    this._errHandler.sync(this);
-                    _la = this._input.LA(1);
-                }
-            }
-
-            this.state = 59;
-            this.match(BaserowFormula.CLOSE_PAREN);
-            break;
-        default:
-            throw new antlr4.error.NoViableAltException(this);
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
         }
-        this._ctx.stop = this._input.LT(-1);
-        this.state = 79;
-        this._errHandler.sync(this);
-        var _alt = this._interp.adaptivePredict(this._input,5,this._ctx)
-        while(_alt!=2 && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
-            if(_alt===1) {
-                if(this._parseListeners!==null) {
-                    this.triggerExitRuleEvent();
-                }
-                _prevctx = localctx;
-                this.state = 77;
-                this._errHandler.sync(this);
-                var la_ = this._interp.adaptivePredict(this._input,4,this._ctx);
-                switch(la_) {
-                case 1:
-                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
-                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
-                    this.state = 63;
-                    if (!( this.precpred(this._ctx, 8))) {
-                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 8)");
-                    }
-                    this.state = 64;
-                    localctx.op = this._input.LT(1);
-                    _la = this._input.LA(1);
-                    if(!(_la===BaserowFormula.STAR || _la===BaserowFormula.SLASH)) {
-                        localctx.op = this._errHandler.recoverInline(this);
-                    }
-                    else {
-                    	this._errHandler.reportMatch(this);
-                        this.consume();
-                    }
-                    this.state = 65;
-                    this.expr(9);
-                    break;
-
-                case 2:
-                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
-                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
-                    this.state = 66;
-                    if (!( this.precpred(this._ctx, 7))) {
-                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 7)");
-                    }
-                    this.state = 67;
-                    localctx.op = this._input.LT(1);
-                    _la = this._input.LA(1);
-                    if(!(_la===BaserowFormula.MINUS || _la===BaserowFormula.PLUS)) {
-                        localctx.op = this._errHandler.recoverInline(this);
-                    }
-                    else {
-                    	this._errHandler.reportMatch(this);
-                        this.consume();
-                    }
-                    this.state = 68;
-                    this.expr(8);
-                    break;
-
-                case 3:
-                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
-                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
-                    this.state = 69;
-                    if (!( this.precpred(this._ctx, 6))) {
-                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 6)");
-                    }
-                    this.state = 70;
-                    localctx.op = this._input.LT(1);
-                    _la = this._input.LA(1);
-                    if(!(((((_la - 41)) & ~0x1f) == 0 && ((1 << (_la - 41)) & ((1 << (BaserowFormula.GT - 41)) | (1 << (BaserowFormula.GTE - 41)) | (1 << (BaserowFormula.LT - 41)) | (1 << (BaserowFormula.LTE - 41)))) !== 0))) {
-                        localctx.op = this._errHandler.recoverInline(this);
-                    }
-                    else {
-                    	this._errHandler.reportMatch(this);
-                        this.consume();
-                    }
-                    this.state = 71;
-                    this.expr(7);
-                    break;
-
-                case 4:
-                    localctx = new BinaryOpContext(this, new ExprContext(this, _parentctx, _parentState));
-                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
-                    this.state = 72;
-                    if (!( this.precpred(this._ctx, 5))) {
-                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 5)");
-                    }
-                    this.state = 73;
-                    localctx.op = this._input.LT(1);
-                    _la = this._input.LA(1);
-                    if(!(_la===BaserowFormula.BANG_EQUAL || _la===BaserowFormula.EQUAL)) {
-                        localctx.op = this._errHandler.recoverInline(this);
-                    }
-                    else {
-                    	this._errHandler.reportMatch(this);
-                        this.consume();
-                    }
-                    this.state = 74;
-                    this.expr(6);
-                    break;
-
-                case 5:
-                    localctx = new RightWhitespaceOrCommentsContext(this, new ExprContext(this, _parentctx, _parentState));
-                    this.pushNewRecursionContext(localctx, _startState, BaserowFormula.RULE_expr);
-                    this.state = 75;
-                    if (!( this.precpred(this._ctx, 10))) {
-                        throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 10)");
-                    }
-                    this.state = 76;
-                    this.ws_or_comment();
-                    break;
-
-                } 
-            }
-            this.state = 81;
-            this._errHandler.sync(this);
-            _alt = this._interp.adaptivePredict(this._input,5,this._ctx);
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
         }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_ws_or_comment;
+    }
 
-    } catch( error) {
-        if(error instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = error;
-	        this._errHandler.reportError(this, error);
-	        this._errHandler.recover(this, error);
+	BLOCK_COMMENT() {
+	    return this.getToken(BaserowFormula.BLOCK_COMMENT, 0);
+	};
+
+	LINE_COMMENT() {
+	    return this.getToken(BaserowFormula.LINE_COMMENT, 0);
+	};
+
+	WHITESPACE() {
+	    return this.getToken(BaserowFormula.WHITESPACE, 0);
+	};
+
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterWs_or_comment(this);
+		}
+	}
+
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitWs_or_comment(this);
+		}
+	}
+
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitWs_or_comment(this);
 	    } else {
-	    	throw error;
+	        return visitor.visitChildren(this);
 	    }
-    } finally {
-        this.unrollRecursionContexts(_parentctx)
-    }
-    return localctx;
-};
+	}
 
 
-function Ws_or_commentContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_ws_or_comment;
-    return this;
 }
 
-Ws_or_commentContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-Ws_or_commentContext.prototype.constructor = Ws_or_commentContext;
 
-Ws_or_commentContext.prototype.BLOCK_COMMENT = function() {
-    return this.getToken(BaserowFormula.BLOCK_COMMENT, 0);
-};
 
-Ws_or_commentContext.prototype.LINE_COMMENT = function() {
-    return this.getToken(BaserowFormula.LINE_COMMENT, 0);
-};
+class Func_nameContext extends antlr4.ParserRuleContext {
 
-Ws_or_commentContext.prototype.WHITESPACE = function() {
-    return this.getToken(BaserowFormula.WHITESPACE, 0);
-};
-
-Ws_or_commentContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterWs_or_comment(this);
-	}
-};
-
-Ws_or_commentContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitWs_or_comment(this);
-	}
-};
-
-Ws_or_commentContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitWs_or_comment(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
+        }
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
+        }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_func_name;
     }
-};
 
+	identifier() {
+	    return this.getTypedRuleContext(IdentifierContext,0);
+	};
 
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterFunc_name(this);
+		}
+	}
 
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitFunc_name(this);
+		}
+	}
 
-BaserowFormula.Ws_or_commentContext = Ws_or_commentContext;
-
-BaserowFormula.prototype.ws_or_comment = function() {
-
-    var localctx = new Ws_or_commentContext(this, this._ctx, this.state);
-    this.enterRule(localctx, 4, BaserowFormula.RULE_ws_or_comment);
-    var _la = 0; // Token type
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 82;
-        _la = this._input.LA(1);
-        if(!((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << BaserowFormula.BLOCK_COMMENT) | (1 << BaserowFormula.LINE_COMMENT) | (1 << BaserowFormula.WHITESPACE))) !== 0))) {
-        this._errHandler.recoverInline(this);
-        }
-        else {
-        	this._errHandler.reportMatch(this);
-            this.consume();
-        }
-    } catch (re) {
-    	if(re instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = re;
-	        this._errHandler.reportError(this, re);
-	        this._errHandler.recover(this, re);
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitFunc_name(this);
 	    } else {
-	    	throw re;
+	        return visitor.visitChildren(this);
 	    }
-    } finally {
-        this.exitRule();
-    }
-    return localctx;
-};
+	}
 
 
-function Func_nameContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_func_name;
-    return this;
 }
 
-Func_nameContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-Func_nameContext.prototype.constructor = Func_nameContext;
 
-Func_nameContext.prototype.identifier = function() {
-    return this.getTypedRuleContext(IdentifierContext,0);
-};
 
-Func_nameContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterFunc_name(this);
-	}
-};
+class Field_referenceContext extends antlr4.ParserRuleContext {
 
-Func_nameContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitFunc_name(this);
-	}
-};
-
-Func_nameContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitFunc_name(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
+        }
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
+        }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_field_reference;
     }
-};
 
+	SINGLEQ_STRING_LITERAL() {
+	    return this.getToken(BaserowFormula.SINGLEQ_STRING_LITERAL, 0);
+	};
 
+	DOUBLEQ_STRING_LITERAL() {
+	    return this.getToken(BaserowFormula.DOUBLEQ_STRING_LITERAL, 0);
+	};
 
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterField_reference(this);
+		}
+	}
 
-BaserowFormula.Func_nameContext = Func_nameContext;
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitField_reference(this);
+		}
+	}
 
-BaserowFormula.prototype.func_name = function() {
-
-    var localctx = new Func_nameContext(this, this._ctx, this.state);
-    this.enterRule(localctx, 6, BaserowFormula.RULE_func_name);
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 84;
-        this.identifier();
-    } catch (re) {
-    	if(re instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = re;
-	        this._errHandler.reportError(this, re);
-	        this._errHandler.recover(this, re);
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitField_reference(this);
 	    } else {
-	    	throw re;
+	        return visitor.visitChildren(this);
 	    }
-    } finally {
-        this.exitRule();
-    }
-    return localctx;
-};
+	}
 
 
-function Field_referenceContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_field_reference;
-    return this;
 }
 
-Field_referenceContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-Field_referenceContext.prototype.constructor = Field_referenceContext;
 
-Field_referenceContext.prototype.SINGLEQ_STRING_LITERAL = function() {
-    return this.getToken(BaserowFormula.SINGLEQ_STRING_LITERAL, 0);
-};
 
-Field_referenceContext.prototype.DOUBLEQ_STRING_LITERAL = function() {
-    return this.getToken(BaserowFormula.DOUBLEQ_STRING_LITERAL, 0);
-};
+class IdentifierContext extends antlr4.ParserRuleContext {
 
-Field_referenceContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterField_reference(this);
-	}
-};
-
-Field_referenceContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitField_reference(this);
-	}
-};
-
-Field_referenceContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitField_reference(this);
-    } else {
-        return visitor.visitChildren(this);
+    constructor(parser, parent, invokingState) {
+        if(parent===undefined) {
+            parent = null;
+        }
+        if(invokingState===undefined || invokingState===null) {
+            invokingState = -1;
+        }
+        super(parent, invokingState);
+        this.parser = parser;
+        this.ruleIndex = BaserowFormula.RULE_identifier;
     }
-};
 
+	IDENTIFIER() {
+	    return this.getToken(BaserowFormula.IDENTIFIER, 0);
+	};
 
+	IDENTIFIER_UNICODE() {
+	    return this.getToken(BaserowFormula.IDENTIFIER_UNICODE, 0);
+	};
 
+	enterRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.enterIdentifier(this);
+		}
+	}
 
-BaserowFormula.Field_referenceContext = Field_referenceContext;
+	exitRule(listener) {
+	    if(listener instanceof BaserowFormulaListener ) {
+	        listener.exitIdentifier(this);
+		}
+	}
 
-BaserowFormula.prototype.field_reference = function() {
-
-    var localctx = new Field_referenceContext(this, this._ctx, this.state);
-    this.enterRule(localctx, 8, BaserowFormula.RULE_field_reference);
-    var _la = 0; // Token type
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 86;
-        _la = this._input.LA(1);
-        if(!(_la===BaserowFormula.SINGLEQ_STRING_LITERAL || _la===BaserowFormula.DOUBLEQ_STRING_LITERAL)) {
-        this._errHandler.recoverInline(this);
-        }
-        else {
-        	this._errHandler.reportMatch(this);
-            this.consume();
-        }
-    } catch (re) {
-    	if(re instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = re;
-	        this._errHandler.reportError(this, re);
-	        this._errHandler.recover(this, re);
+	accept(visitor) {
+	    if ( visitor instanceof BaserowFormulaVisitor ) {
+	        return visitor.visitIdentifier(this);
 	    } else {
-	    	throw re;
+	        return visitor.visitChildren(this);
 	    }
-    } finally {
-        this.exitRule();
-    }
-    return localctx;
-};
+	}
 
 
-function IdentifierContext(parser, parent, invokingState) {
-	if(parent===undefined) {
-	    parent = null;
-	}
-	if(invokingState===undefined || invokingState===null) {
-		invokingState = -1;
-	}
-	antlr4.ParserRuleContext.call(this, parent, invokingState);
-    this.parser = parser;
-    this.ruleIndex = BaserowFormula.RULE_identifier;
-    return this;
 }
 
-IdentifierContext.prototype = Object.create(antlr4.ParserRuleContext.prototype);
-IdentifierContext.prototype.constructor = IdentifierContext;
-
-IdentifierContext.prototype.IDENTIFIER = function() {
-    return this.getToken(BaserowFormula.IDENTIFIER, 0);
-};
-
-IdentifierContext.prototype.IDENTIFIER_UNICODE = function() {
-    return this.getToken(BaserowFormula.IDENTIFIER_UNICODE, 0);
-};
-
-IdentifierContext.prototype.enterRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.enterIdentifier(this);
-	}
-};
-
-IdentifierContext.prototype.exitRule = function(listener) {
-    if(listener instanceof BaserowFormulaListener ) {
-        listener.exitIdentifier(this);
-	}
-};
-
-IdentifierContext.prototype.accept = function(visitor) {
-    if ( visitor instanceof BaserowFormulaVisitor ) {
-        return visitor.visitIdentifier(this);
-    } else {
-        return visitor.visitChildren(this);
-    }
-};
 
 
 
-
-BaserowFormula.IdentifierContext = IdentifierContext;
-
-BaserowFormula.prototype.identifier = function() {
-
-    var localctx = new IdentifierContext(this, this._ctx, this.state);
-    this.enterRule(localctx, 10, BaserowFormula.RULE_identifier);
-    var _la = 0; // Token type
-    try {
-        this.enterOuterAlt(localctx, 1);
-        this.state = 88;
-        _la = this._input.LA(1);
-        if(!(_la===BaserowFormula.IDENTIFIER || _la===BaserowFormula.IDENTIFIER_UNICODE)) {
-        this._errHandler.recoverInline(this);
-        }
-        else {
-        	this._errHandler.reportMatch(this);
-            this.consume();
-        }
-    } catch (re) {
-    	if(re instanceof antlr4.error.RecognitionException) {
-	        localctx.exception = re;
-	        this._errHandler.reportError(this, re);
-	        this._errHandler.recover(this, re);
-	    } else {
-	    	throw re;
-	    }
-    } finally {
-        this.exitRule();
-    }
-    return localctx;
-};
-
-
-BaserowFormula.prototype.sempred = function(localctx, ruleIndex, predIndex) {
-	switch(ruleIndex) {
-	case 1:
-			return this.expr_sempred(localctx, predIndex);
-    default:
-        throw "No predicate with index:" + ruleIndex;
-   }
-};
-
-BaserowFormula.prototype.expr_sempred = function(localctx, predIndex) {
-	switch(predIndex) {
-		case 0:
-			return this.precpred(this._ctx, 8);
-		case 1:
-			return this.precpred(this._ctx, 7);
-		case 2:
-			return this.precpred(this._ctx, 6);
-		case 3:
-			return this.precpred(this._ctx, 5);
-		case 4:
-			return this.precpred(this._ctx, 10);
-		default:
-			throw "No predicate with index:" + predIndex;
-	}
-};
-
-
-exports.BaserowFormula = BaserowFormula;
+BaserowFormula.RootContext = RootContext; 
+BaserowFormula.ExprContext = ExprContext; 
+BaserowFormula.Ws_or_commentContext = Ws_or_commentContext; 
+BaserowFormula.Func_nameContext = Func_nameContext; 
+BaserowFormula.Field_referenceContext = Field_referenceContext; 
+BaserowFormula.IdentifierContext = IdentifierContext; 
diff --git a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaLexer.js b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaLexer.js
index e54d71228..bbf8e35b6 100644
--- a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaLexer.js
+++ b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaLexer.js
@@ -1,13 +1,13 @@
-// Generated from BaserowFormulaLexer.g4 by ANTLR 4.8
+// Generated from BaserowFormulaLexer.g4 by ANTLR 4.9
 // jshint ignore: start
-var antlr4 = require('antlr4/index');
+import antlr4 from 'antlr4';
 
 
 
-var serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964",
-    "\u0002U\u028b\b\u0001\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004",
-    "\u0004\t\u0004\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007\t",
-    "\u0007\u0004\b\t\b\u0004\t\t\t\u0004\n\t\n\u0004\u000b\t\u000b\u0004",
+const serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786",
+    "\u5964\u0002U\u028b\b\u0001\u0004\u0002\t\u0002\u0004\u0003\t\u0003",
+    "\u0004\u0004\t\u0004\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007",
+    "\t\u0007\u0004\b\t\b\u0004\t\t\t\u0004\n\t\n\u0004\u000b\t\u000b\u0004",
     "\f\t\f\u0004\r\t\r\u0004\u000e\t\u000e\u0004\u000f\t\u000f\u0004\u0010",
     "\t\u0010\u0004\u0011\t\u0011\u0004\u0012\t\u0012\u0004\u0013\t\u0013",
     "\u0004\u0014\t\u0014\u0004\u0015\t\u0015\u0004\u0016\t\u0016\u0004\u0017",
@@ -408,25 +408,81 @@ var serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964",
     "\u0002"].join("");
 
 
-var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
+const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
 
-var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); });
+const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
 
-function BaserowFormulaLexer(input) {
-	antlr4.Lexer.call(this, input);
-    this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache());
-    return this;
+export default class BaserowFormulaLexer extends antlr4.Lexer {
+
+    static grammarFileName = "BaserowFormulaLexer.g4";
+    static channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ];
+	static modeNames = [ "DEFAULT_MODE" ];
+	static literalNames = [ null, null, null, null, null, null, null, null, 
+                         null, "','", "':'", "'::'", "'$'", "'$$'", "'*'", 
+                         "'('", "')'", "'['", "']'", null, null, null, null, 
+                         null, "'.'", null, null, null, null, "'&'", "'&&'", 
+                         "'&<'", "'@@'", "'@>'", "'@'", "'!'", "'!!'", "'!='", 
+                         "'^'", "'='", "'=>'", "'>'", "'>='", "'>>'", "'#'", 
+                         "'#='", "'#>'", "'#>>'", "'##'", "'->'", "'->>'", 
+                         "'-|-'", "'<'", "'<='", "'<@'", "'<^'", "'<>'", 
+                         "'<->'", "'<<'", "'<<='", "'<?>'", "'-'", "'%'", 
+                         "'|'", "'||'", "'||/'", "'|/'", "'+'", "'?'", "'?&'", 
+                         "'?#'", "'?-'", "'?|'", "'/'", "'~'", "'~='", "'~>=~'", 
+                         "'~>~'", "'~<=~'", "'~<~'", "'~*'", "'~~'", "';'" ];
+	static symbolicNames = [ null, "BLOCK_COMMENT", "LINE_COMMENT", "WHITESPACE", 
+                          "TRUE", "FALSE", "FIELD", "FIELDBYID", "LOOKUP", 
+                          "COMMA", "COLON", "COLON_COLON", "DOLLAR", "DOLLAR_DOLLAR", 
+                          "STAR", "OPEN_PAREN", "CLOSE_PAREN", "OPEN_BRACKET", 
+                          "CLOSE_BRACKET", "BIT_STRING", "REGEX_STRING", 
+                          "NUMERIC_LITERAL", "INTEGER_LITERAL", "HEX_INTEGER_LITERAL", 
+                          "DOT", "SINGLEQ_STRING_LITERAL", "DOUBLEQ_STRING_LITERAL", 
+                          "IDENTIFIER", "IDENTIFIER_UNICODE", "AMP", "AMP_AMP", 
+                          "AMP_LT", "AT_AT", "AT_GT", "AT_SIGN", "BANG", 
+                          "BANG_BANG", "BANG_EQUAL", "CARET", "EQUAL", "EQUAL_GT", 
+                          "GT", "GTE", "GT_GT", "HASH", "HASH_EQ", "HASH_GT", 
+                          "HASH_GT_GT", "HASH_HASH", "HYPHEN_GT", "HYPHEN_GT_GT", 
+                          "HYPHEN_PIPE_HYPHEN", "LT", "LTE", "LT_AT", "LT_CARET", 
+                          "LT_GT", "LT_HYPHEN_GT", "LT_LT", "LT_LT_EQ", 
+                          "LT_QMARK_GT", "MINUS", "PERCENT", "PIPE", "PIPE_PIPE", 
+                          "PIPE_PIPE_SLASH", "PIPE_SLASH", "PLUS", "QMARK", 
+                          "QMARK_AMP", "QMARK_HASH", "QMARK_HYPHEN", "QMARK_PIPE", 
+                          "SLASH", "TIL", "TIL_EQ", "TIL_GTE_TIL", "TIL_GT_TIL", 
+                          "TIL_LTE_TIL", "TIL_LT_TIL", "TIL_STAR", "TIL_TIL", 
+                          "SEMI", "ErrorCharacter" ];
+	static ruleNames = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", 
+                      "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", 
+                      "U", "V", "W", "X", "Y", "Z", "UNDERSCORE", "HEX_DIGIT", 
+                      "DEC_DIGIT", "DQUOTA_STRING", "SQUOTA_STRING", "BQUOTA_STRING", 
+                      "BLOCK_COMMENT", "LINE_COMMENT", "WHITESPACE", "TRUE", 
+                      "FALSE", "FIELD", "FIELDBYID", "LOOKUP", "COMMA", 
+                      "COLON", "COLON_COLON", "DOLLAR", "DOLLAR_DOLLAR", 
+                      "STAR", "OPEN_PAREN", "CLOSE_PAREN", "OPEN_BRACKET", 
+                      "CLOSE_BRACKET", "BIT_STRING", "REGEX_STRING", "NUMERIC_LITERAL", 
+                      "INTEGER_LITERAL", "HEX_INTEGER_LITERAL", "DOT", "SINGLEQ_STRING_LITERAL", 
+                      "DOUBLEQ_STRING_LITERAL", "IDENTIFIER", "IDENTIFIER_UNICODE", 
+                      "AMP", "AMP_AMP", "AMP_LT", "AT_AT", "AT_GT", "AT_SIGN", 
+                      "BANG", "BANG_BANG", "BANG_EQUAL", "CARET", "EQUAL", 
+                      "EQUAL_GT", "GT", "GTE", "GT_GT", "HASH", "HASH_EQ", 
+                      "HASH_GT", "HASH_GT_GT", "HASH_HASH", "HYPHEN_GT", 
+                      "HYPHEN_GT_GT", "HYPHEN_PIPE_HYPHEN", "LT", "LTE", 
+                      "LT_AT", "LT_CARET", "LT_GT", "LT_HYPHEN_GT", "LT_LT", 
+                      "LT_LT_EQ", "LT_QMARK_GT", "MINUS", "PERCENT", "PIPE", 
+                      "PIPE_PIPE", "PIPE_PIPE_SLASH", "PIPE_SLASH", "PLUS", 
+                      "QMARK", "QMARK_AMP", "QMARK_HASH", "QMARK_HYPHEN", 
+                      "QMARK_PIPE", "SLASH", "TIL", "TIL_EQ", "TIL_GTE_TIL", 
+                      "TIL_GT_TIL", "TIL_LTE_TIL", "TIL_LT_TIL", "TIL_STAR", 
+                      "TIL_TIL", "SEMI", "ErrorCharacter" ];
+
+    constructor(input) {
+        super(input)
+        this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache());
+    }
+
+    get atn() {
+        return atn;
+    }
 }
 
-BaserowFormulaLexer.prototype = Object.create(antlr4.Lexer.prototype);
-BaserowFormulaLexer.prototype.constructor = BaserowFormulaLexer;
-
-Object.defineProperty(BaserowFormulaLexer.prototype, "atn", {
-        get : function() {
-                return atn;
-        }
-});
-
 BaserowFormulaLexer.EOF = antlr4.Token.EOF;
 BaserowFormulaLexer.BLOCK_COMMENT = 1;
 BaserowFormulaLexer.LINE_COMMENT = 2;
@@ -512,110 +568,5 @@ BaserowFormulaLexer.TIL_TIL = 81;
 BaserowFormulaLexer.SEMI = 82;
 BaserowFormulaLexer.ErrorCharacter = 83;
 
-BaserowFormulaLexer.prototype.channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ];
-
-BaserowFormulaLexer.prototype.modeNames = [ "DEFAULT_MODE" ];
-
-BaserowFormulaLexer.prototype.literalNames = [ null, null, null, null, null, 
-                                               null, null, null, null, "','", 
-                                               "':'", "'::'", "'$'", "'$$'", 
-                                               "'*'", "'('", "')'", "'['", 
-                                               "']'", null, null, null, 
-                                               null, null, "'.'", null, 
-                                               null, null, null, "'&'", 
-                                               "'&&'", "'&<'", "'@@'", "'@>'", 
-                                               "'@'", "'!'", "'!!'", "'!='", 
-                                               "'^'", "'='", "'=>'", "'>'", 
-                                               "'>='", "'>>'", "'#'", "'#='", 
-                                               "'#>'", "'#>>'", "'##'", 
-                                               "'->'", "'->>'", "'-|-'", 
-                                               "'<'", "'<='", "'<@'", "'<^'", 
-                                               "'<>'", "'<->'", "'<<'", 
-                                               "'<<='", "'<?>'", "'-'", 
-                                               "'%'", "'|'", "'||'", "'||/'", 
-                                               "'|/'", "'+'", "'?'", "'?&'", 
-                                               "'?#'", "'?-'", "'?|'", "'/'", 
-                                               "'~'", "'~='", "'~>=~'", 
-                                               "'~>~'", "'~<=~'", "'~<~'", 
-                                               "'~*'", "'~~'", "';'" ];
-
-BaserowFormulaLexer.prototype.symbolicNames = [ null, "BLOCK_COMMENT", "LINE_COMMENT", 
-                                                "WHITESPACE", "TRUE", "FALSE", 
-                                                "FIELD", "FIELDBYID", "LOOKUP", 
-                                                "COMMA", "COLON", "COLON_COLON", 
-                                                "DOLLAR", "DOLLAR_DOLLAR", 
-                                                "STAR", "OPEN_PAREN", "CLOSE_PAREN", 
-                                                "OPEN_BRACKET", "CLOSE_BRACKET", 
-                                                "BIT_STRING", "REGEX_STRING", 
-                                                "NUMERIC_LITERAL", "INTEGER_LITERAL", 
-                                                "HEX_INTEGER_LITERAL", "DOT", 
-                                                "SINGLEQ_STRING_LITERAL", 
-                                                "DOUBLEQ_STRING_LITERAL", 
-                                                "IDENTIFIER", "IDENTIFIER_UNICODE", 
-                                                "AMP", "AMP_AMP", "AMP_LT", 
-                                                "AT_AT", "AT_GT", "AT_SIGN", 
-                                                "BANG", "BANG_BANG", "BANG_EQUAL", 
-                                                "CARET", "EQUAL", "EQUAL_GT", 
-                                                "GT", "GTE", "GT_GT", "HASH", 
-                                                "HASH_EQ", "HASH_GT", "HASH_GT_GT", 
-                                                "HASH_HASH", "HYPHEN_GT", 
-                                                "HYPHEN_GT_GT", "HYPHEN_PIPE_HYPHEN", 
-                                                "LT", "LTE", "LT_AT", "LT_CARET", 
-                                                "LT_GT", "LT_HYPHEN_GT", 
-                                                "LT_LT", "LT_LT_EQ", "LT_QMARK_GT", 
-                                                "MINUS", "PERCENT", "PIPE", 
-                                                "PIPE_PIPE", "PIPE_PIPE_SLASH", 
-                                                "PIPE_SLASH", "PLUS", "QMARK", 
-                                                "QMARK_AMP", "QMARK_HASH", 
-                                                "QMARK_HYPHEN", "QMARK_PIPE", 
-                                                "SLASH", "TIL", "TIL_EQ", 
-                                                "TIL_GTE_TIL", "TIL_GT_TIL", 
-                                                "TIL_LTE_TIL", "TIL_LT_TIL", 
-                                                "TIL_STAR", "TIL_TIL", "SEMI", 
-                                                "ErrorCharacter" ];
-
-BaserowFormulaLexer.prototype.ruleNames = [ "A", "B", "C", "D", "E", "F", 
-                                            "G", "H", "I", "J", "K", "L", 
-                                            "M", "N", "O", "P", "Q", "R", 
-                                            "S", "T", "U", "V", "W", "X", 
-                                            "Y", "Z", "UNDERSCORE", "HEX_DIGIT", 
-                                            "DEC_DIGIT", "DQUOTA_STRING", 
-                                            "SQUOTA_STRING", "BQUOTA_STRING", 
-                                            "BLOCK_COMMENT", "LINE_COMMENT", 
-                                            "WHITESPACE", "TRUE", "FALSE", 
-                                            "FIELD", "FIELDBYID", "LOOKUP", 
-                                            "COMMA", "COLON", "COLON_COLON", 
-                                            "DOLLAR", "DOLLAR_DOLLAR", "STAR", 
-                                            "OPEN_PAREN", "CLOSE_PAREN", 
-                                            "OPEN_BRACKET", "CLOSE_BRACKET", 
-                                            "BIT_STRING", "REGEX_STRING", 
-                                            "NUMERIC_LITERAL", "INTEGER_LITERAL", 
-                                            "HEX_INTEGER_LITERAL", "DOT", 
-                                            "SINGLEQ_STRING_LITERAL", "DOUBLEQ_STRING_LITERAL", 
-                                            "IDENTIFIER", "IDENTIFIER_UNICODE", 
-                                            "AMP", "AMP_AMP", "AMP_LT", 
-                                            "AT_AT", "AT_GT", "AT_SIGN", 
-                                            "BANG", "BANG_BANG", "BANG_EQUAL", 
-                                            "CARET", "EQUAL", "EQUAL_GT", 
-                                            "GT", "GTE", "GT_GT", "HASH", 
-                                            "HASH_EQ", "HASH_GT", "HASH_GT_GT", 
-                                            "HASH_HASH", "HYPHEN_GT", "HYPHEN_GT_GT", 
-                                            "HYPHEN_PIPE_HYPHEN", "LT", 
-                                            "LTE", "LT_AT", "LT_CARET", 
-                                            "LT_GT", "LT_HYPHEN_GT", "LT_LT", 
-                                            "LT_LT_EQ", "LT_QMARK_GT", "MINUS", 
-                                            "PERCENT", "PIPE", "PIPE_PIPE", 
-                                            "PIPE_PIPE_SLASH", "PIPE_SLASH", 
-                                            "PLUS", "QMARK", "QMARK_AMP", 
-                                            "QMARK_HASH", "QMARK_HYPHEN", 
-                                            "QMARK_PIPE", "SLASH", "TIL", 
-                                            "TIL_EQ", "TIL_GTE_TIL", "TIL_GT_TIL", 
-                                            "TIL_LTE_TIL", "TIL_LT_TIL", 
-                                            "TIL_STAR", "TIL_TIL", "SEMI", 
-                                            "ErrorCharacter" ];
-
-BaserowFormulaLexer.prototype.grammarFileName = "BaserowFormulaLexer.g4";
 
 
-exports.BaserowFormulaLexer = BaserowFormulaLexer;
-
diff --git a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaListener.js b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaListener.js
index f9eecbb0b..fa28a1191 100644
--- a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaListener.js
+++ b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaListener.js
@@ -1,168 +1,162 @@
-// Generated from BaserowFormula.g4 by ANTLR 4.8
+// Generated from BaserowFormula.g4 by ANTLR 4.9
 // jshint ignore: start
-var antlr4 = require('antlr4/index');
+import antlr4 from 'antlr4';
 
 // This class defines a complete listener for a parse tree produced by BaserowFormula.
-function BaserowFormulaListener() {
-	antlr4.tree.ParseTreeListener.call(this);
-	return this;
-}
+export default class BaserowFormulaListener extends antlr4.tree.ParseTreeListener {
 
-BaserowFormulaListener.prototype = Object.create(antlr4.tree.ParseTreeListener.prototype);
-BaserowFormulaListener.prototype.constructor = BaserowFormulaListener;
+	// Enter a parse tree produced by BaserowFormula#root.
+	enterRoot(ctx) {
+	}
 
-// Enter a parse tree produced by BaserowFormula#root.
-BaserowFormulaListener.prototype.enterRoot = function(ctx) {
-};
-
-// Exit a parse tree produced by BaserowFormula#root.
-BaserowFormulaListener.prototype.exitRoot = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#root.
+	exitRoot(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#FieldReference.
-BaserowFormulaListener.prototype.enterFieldReference = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#FieldReference.
+	enterFieldReference(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#FieldReference.
-BaserowFormulaListener.prototype.exitFieldReference = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#FieldReference.
+	exitFieldReference(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#StringLiteral.
-BaserowFormulaListener.prototype.enterStringLiteral = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#StringLiteral.
+	enterStringLiteral(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#StringLiteral.
-BaserowFormulaListener.prototype.exitStringLiteral = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#StringLiteral.
+	exitStringLiteral(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#Brackets.
-BaserowFormulaListener.prototype.enterBrackets = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#Brackets.
+	enterBrackets(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#Brackets.
-BaserowFormulaListener.prototype.exitBrackets = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#Brackets.
+	exitBrackets(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#BooleanLiteral.
-BaserowFormulaListener.prototype.enterBooleanLiteral = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#BooleanLiteral.
+	enterBooleanLiteral(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#BooleanLiteral.
-BaserowFormulaListener.prototype.exitBooleanLiteral = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#BooleanLiteral.
+	exitBooleanLiteral(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
-BaserowFormulaListener.prototype.enterRightWhitespaceOrComments = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
+	enterRightWhitespaceOrComments(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
-BaserowFormulaListener.prototype.exitRightWhitespaceOrComments = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
+	exitRightWhitespaceOrComments(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#DecimalLiteral.
-BaserowFormulaListener.prototype.enterDecimalLiteral = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#DecimalLiteral.
+	enterDecimalLiteral(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#DecimalLiteral.
-BaserowFormulaListener.prototype.exitDecimalLiteral = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#DecimalLiteral.
+	exitDecimalLiteral(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
-BaserowFormulaListener.prototype.enterLeftWhitespaceOrComments = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
+	enterLeftWhitespaceOrComments(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
-BaserowFormulaListener.prototype.exitLeftWhitespaceOrComments = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
+	exitLeftWhitespaceOrComments(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#FunctionCall.
-BaserowFormulaListener.prototype.enterFunctionCall = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#FunctionCall.
+	enterFunctionCall(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#FunctionCall.
-BaserowFormulaListener.prototype.exitFunctionCall = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#FunctionCall.
+	exitFunctionCall(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#FieldByIdReference.
-BaserowFormulaListener.prototype.enterFieldByIdReference = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#FieldByIdReference.
+	enterFieldByIdReference(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#FieldByIdReference.
-BaserowFormulaListener.prototype.exitFieldByIdReference = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#FieldByIdReference.
+	exitFieldByIdReference(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#LookupFieldReference.
-BaserowFormulaListener.prototype.enterLookupFieldReference = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#LookupFieldReference.
+	enterLookupFieldReference(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#LookupFieldReference.
-BaserowFormulaListener.prototype.exitLookupFieldReference = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#LookupFieldReference.
+	exitLookupFieldReference(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#IntegerLiteral.
-BaserowFormulaListener.prototype.enterIntegerLiteral = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#IntegerLiteral.
+	enterIntegerLiteral(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#IntegerLiteral.
-BaserowFormulaListener.prototype.exitIntegerLiteral = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#IntegerLiteral.
+	exitIntegerLiteral(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#BinaryOp.
-BaserowFormulaListener.prototype.enterBinaryOp = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#BinaryOp.
+	enterBinaryOp(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#BinaryOp.
-BaserowFormulaListener.prototype.exitBinaryOp = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#BinaryOp.
+	exitBinaryOp(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#ws_or_comment.
-BaserowFormulaListener.prototype.enterWs_or_comment = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#ws_or_comment.
+	enterWs_or_comment(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#ws_or_comment.
-BaserowFormulaListener.prototype.exitWs_or_comment = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#ws_or_comment.
+	exitWs_or_comment(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#func_name.
-BaserowFormulaListener.prototype.enterFunc_name = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#func_name.
+	enterFunc_name(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#func_name.
-BaserowFormulaListener.prototype.exitFunc_name = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#func_name.
+	exitFunc_name(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#field_reference.
-BaserowFormulaListener.prototype.enterField_reference = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#field_reference.
+	enterField_reference(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#field_reference.
-BaserowFormulaListener.prototype.exitField_reference = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#field_reference.
+	exitField_reference(ctx) {
+	}
 
 
-// Enter a parse tree produced by BaserowFormula#identifier.
-BaserowFormulaListener.prototype.enterIdentifier = function(ctx) {
-};
+	// Enter a parse tree produced by BaserowFormula#identifier.
+	enterIdentifier(ctx) {
+	}
 
-// Exit a parse tree produced by BaserowFormula#identifier.
-BaserowFormulaListener.prototype.exitIdentifier = function(ctx) {
-};
+	// Exit a parse tree produced by BaserowFormula#identifier.
+	exitIdentifier(ctx) {
+	}
 
 
 
-exports.BaserowFormulaListener = BaserowFormulaListener;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaVisitor.js b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaVisitor.js
index 92e436e74..e8ed9bc1c 100644
--- a/web-frontend/modules/database/formula/parser/generated/BaserowFormulaVisitor.js
+++ b/web-frontend/modules/database/formula/parser/generated/BaserowFormulaVisitor.js
@@ -1,118 +1,112 @@
-// Generated from BaserowFormula.g4 by ANTLR 4.8
+// Generated from BaserowFormula.g4 by ANTLR 4.9
 // jshint ignore: start
-var antlr4 = require('antlr4/index');
+import antlr4 from 'antlr4';
 
 // This class defines a complete generic visitor for a parse tree produced by BaserowFormula.
 
-function BaserowFormulaVisitor() {
-	antlr4.tree.ParseTreeVisitor.call(this);
-	return this;
-}
+export default class BaserowFormulaVisitor extends antlr4.tree.ParseTreeVisitor {
 
-BaserowFormulaVisitor.prototype = Object.create(antlr4.tree.ParseTreeVisitor.prototype);
-BaserowFormulaVisitor.prototype.constructor = BaserowFormulaVisitor;
-
-// Visit a parse tree produced by BaserowFormula#root.
-BaserowFormulaVisitor.prototype.visitRoot = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#root.
+	visitRoot(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#FieldReference.
-BaserowFormulaVisitor.prototype.visitFieldReference = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#FieldReference.
+	visitFieldReference(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#StringLiteral.
-BaserowFormulaVisitor.prototype.visitStringLiteral = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#StringLiteral.
+	visitStringLiteral(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#Brackets.
-BaserowFormulaVisitor.prototype.visitBrackets = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#Brackets.
+	visitBrackets(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#BooleanLiteral.
-BaserowFormulaVisitor.prototype.visitBooleanLiteral = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#BooleanLiteral.
+	visitBooleanLiteral(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
-BaserowFormulaVisitor.prototype.visitRightWhitespaceOrComments = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#RightWhitespaceOrComments.
+	visitRightWhitespaceOrComments(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#DecimalLiteral.
-BaserowFormulaVisitor.prototype.visitDecimalLiteral = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#DecimalLiteral.
+	visitDecimalLiteral(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
-BaserowFormulaVisitor.prototype.visitLeftWhitespaceOrComments = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#LeftWhitespaceOrComments.
+	visitLeftWhitespaceOrComments(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#FunctionCall.
-BaserowFormulaVisitor.prototype.visitFunctionCall = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#FunctionCall.
+	visitFunctionCall(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#FieldByIdReference.
-BaserowFormulaVisitor.prototype.visitFieldByIdReference = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#FieldByIdReference.
+	visitFieldByIdReference(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#LookupFieldReference.
-BaserowFormulaVisitor.prototype.visitLookupFieldReference = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#LookupFieldReference.
+	visitLookupFieldReference(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#IntegerLiteral.
-BaserowFormulaVisitor.prototype.visitIntegerLiteral = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#IntegerLiteral.
+	visitIntegerLiteral(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#BinaryOp.
-BaserowFormulaVisitor.prototype.visitBinaryOp = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#BinaryOp.
+	visitBinaryOp(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#ws_or_comment.
-BaserowFormulaVisitor.prototype.visitWs_or_comment = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#ws_or_comment.
+	visitWs_or_comment(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#func_name.
-BaserowFormulaVisitor.prototype.visitFunc_name = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#func_name.
+	visitFunc_name(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#field_reference.
-BaserowFormulaVisitor.prototype.visitField_reference = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#field_reference.
+	visitField_reference(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
-// Visit a parse tree produced by BaserowFormula#identifier.
-BaserowFormulaVisitor.prototype.visitIdentifier = function(ctx) {
-  return this.visitChildren(ctx);
-};
+	// Visit a parse tree produced by BaserowFormula#identifier.
+	visitIdentifier(ctx) {
+	  return this.visitChildren(ctx);
+	}
 
 
 
-exports.BaserowFormulaVisitor = BaserowFormulaVisitor;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/web-frontend/modules/database/formula/parser/parser.js b/web-frontend/modules/database/formula/parser/parser.js
index 102ff8821..3b8c4de15 100644
--- a/web-frontend/modules/database/formula/parser/parser.js
+++ b/web-frontend/modules/database/formula/parser/parser.js
@@ -1,7 +1,6 @@
 import antlr4 from 'antlr4'
-import { BufferedTokenStream } from 'antlr4/BufferedTokenStream'
-import { BaserowFormulaLexer } from '@baserow/modules/database/formula/parser/generated/BaserowFormulaLexer'
-import { BaserowFormula } from '@baserow/modules/database/formula/parser/generated/BaserowFormula'
+import BaserowFormulaLexer from '@baserow/modules/database/formula/parser/generated/BaserowFormulaLexer'
+import BaserowFormula from '@baserow/modules/database/formula/parser/generated/BaserowFormula'
 import BaserowFormulaParserError from '@baserow/modules/database/formula/parser/errors'
 
 /**
@@ -30,7 +29,7 @@ export default function parseBaserowFormula(formula) {
 export function getTokenStreamForFormula(formula) {
   const chars = new antlr4.InputStream(formula)
   const lexer = new BaserowFormulaLexer(chars)
-  const stream = new BufferedTokenStream(lexer)
+  const stream = new antlr4.CommonTokenStream(lexer)
   stream.lazyInit()
   stream.fill()
   return stream
diff --git a/web-frontend/modules/database/store/view/bufferedRows.js b/web-frontend/modules/database/store/view/bufferedRows.js
index 2d8b19181..c708b4bf7 100644
--- a/web-frontend/modules/database/store/view/bufferedRows.js
+++ b/web-frontend/modules/database/store/view/bufferedRows.js
@@ -47,7 +47,9 @@ export default ({ service, customPopulateRow }) => {
     if (customPopulateRow) {
       customPopulateRow(row)
     }
-    row._ ??= {}
+    if (row._ == null) {
+      row._ = {}
+    }
     // Matching rows for front-end only search is not yet properly
     // supported and tested in this store mixin. Only server-side search
     // implementation is finished.
diff --git a/web-frontend/package.json b/web-frontend/package.json
index f4aa01850..b0948c898 100644
--- a/web-frontend/package.json
+++ b/web-frontend/package.json
@@ -5,6 +5,9 @@
   "description": "Baserow: open source no-code database web frontend.",
   "author": "Bram Wiepjes (Baserow)",
   "license": "MIT",
+  "engines": {
+    "node": ">=16.14.0 <17"
+  },
   "scripts": {
     "build": "nuxt build",
     "build-local": "nuxt build --config-file ./config/nuxt.config.local.js",
@@ -18,7 +21,7 @@
   "dependencies": {
     "@fortawesome/fontawesome-free": "^5.15.3",
     "@nuxtjs/i18n": "^7.2.0",
-    "antlr4": "4.8.0",
+    "antlr4": "4.9.3",
     "async-mutex": "^0.3.1",
     "axios": "^0.25.0",
     "bignumber.js": "^9.0.1",
@@ -32,7 +35,7 @@
     "moment-timezone": "^0.5.33",
     "node-sass": "^6.0.1",
     "normalize-scss": "^7.0.1",
-    "nuxt": "^2.15.7",
+    "nuxt": "^2.15.8",
     "nuxt-env": "^0.1.0",
     "papaparse": "^5.3.1",
     "resize-observer-polyfill": "^1.5.1",
@@ -75,4 +78,4 @@
     "stylelint-webpack-plugin": "^3.0.1",
     "vue-jest": "^3.0.3"
   }
-}
+}
\ No newline at end of file
diff --git a/web-frontend/yarn.lock b/web-frontend/yarn.lock
index 89701e105..e9c3ccc8d 100644
--- a/web-frontend/yarn.lock
+++ b/web-frontend/yarn.lock
@@ -1354,15 +1354,15 @@
     core-js-compat "^3.12.1"
     regenerator-runtime "^0.13.7"
 
-"@nuxt/builder@2.15.7":
-  version "2.15.7"
-  resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.15.7.tgz#4703c9d21756128f4ebfbf14e7b099bee7463626"
-  integrity sha512-vVZvcgvhL05Omp9AuqdDz2zfhBOmCXpVyt1IBUqR99QaorLICGg2iIHC42exj9yN3rBrpURQwb1OrIgt5o5KDQ==
+"@nuxt/builder@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.15.8.tgz#66ead4be0a2ce6932a2b7e521cfe1621e49290e7"
+  integrity sha512-WVhN874LFMdgRiJqpxmeKI+vh5lhCUBVOyR9PhL1m1V/GV3fb+Dqc1BKS6XgayrWAWavPLveCJmQ/FID0puOfQ==
   dependencies:
     "@nuxt/devalue" "^1.2.5"
-    "@nuxt/utils" "2.15.7"
-    "@nuxt/vue-app" "2.15.7"
-    "@nuxt/webpack" "2.15.7"
+    "@nuxt/utils" "2.15.8"
+    "@nuxt/vue-app" "2.15.8"
+    "@nuxt/webpack" "2.15.8"
     chalk "^4.1.1"
     chokidar "^3.5.1"
     consola "^2.15.3"
@@ -1375,13 +1375,13 @@
     serialize-javascript "^5.0.1"
     upath "^2.0.1"
 
-"@nuxt/cli@2.15.7":
-  version "2.15.7"
-  resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.15.7.tgz#21fb8a969bc5e222aa95289fcccc44f9ff7c5549"
-  integrity sha512-rbJqmHuN+ZftSpQNzgiaGP2L2pt45kCbWjCmLUF9pPYQ1pysl9GHVb+1LFf1Wn4wczJckH3Jc9Pl9r2KsLAteA==
+"@nuxt/cli@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.15.8.tgz#3b946ee08c7b5b3223c8952873c65727e775ec30"
+  integrity sha512-KcGIILW/dAjBKea1DHsuLCG1sNzhzETShwT23DhXWO304qL8ljf4ndYKzn2RenzauGRGz7MREta80CbJCkLSHw==
   dependencies:
-    "@nuxt/config" "2.15.7"
-    "@nuxt/utils" "2.15.7"
+    "@nuxt/config" "2.15.8"
+    "@nuxt/utils" "2.15.8"
     boxen "^5.0.1"
     chalk "^4.1.1"
     compression "^1.7.4"