diff --git a/src/qir/parser/Parser.java b/src/qir/parser/Parser.java
deleted file mode 100644
index 70b3b5565c77ad8d39c8244f0900dac824f01418..0000000000000000000000000000000000000000
--- a/src/qir/parser/Parser.java
+++ /dev/null
@@ -1,952 +0,0 @@
-package qir.parser;
-
-import java.math.BigInteger;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.source.SourceSection;
-
-import qir.ast.*;
-import qir.ast.data.*;
-import qir.ast.expression.*;
-import qir.ast.expression.arithmetic.*;
-import qir.ast.expression.logic.*;
-import qir.ast.expression.relational.*;
-import qir.ast.operator.*;
-import qir.types.*;
-import qir.typing.QIRDefaultTypeSystemVisitor;
-
-public class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _stringLiteral = 2;
-	public static final int _numberLiteral = 3;
-	public static final int _doubleLiteral = 4;
-	public static final int maxT = 58;
-
-	static final boolean _T = true;
-	static final boolean _x = false;
-	static final int minErrDist = 2;
-
-	public Token t;    // last recognized token
-	public Token la;   // lookahead token
-	int errDist = minErrDist;
-	
-	public Scanner scanner;
-	private Source source;
-	public Errors errors;
-
-	
-
-	public Parser(final Scanner scanner, final Source source) {
-		this.scanner = scanner;
-		this.source = source;
-		errors = new Errors();
-	}
-
-	void SynErr (int n) {
-		if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
-		errDist = 0;
-	}
-
-	public void SemErr (String msg) {
-		if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
-		errDist = 0;
-	}
-	
-	void Get () {
-		for (;;) {
-			t = la;
-			la = scanner.Scan();
-			if (la.kind <= maxT) {
-				++errDist;
-				break;
-			}
-
-			la = t;
-		}
-	}
-	
-	void Expect (int n) {
-		if (la.kind==n) Get(); else { SynErr(n); }
-	}
-	
-	boolean StartOf (int s) {
-		return set[s][la.kind];
-	}
-	
-	void ExpectWeak (int n, int follow) {
-		if (la.kind == n) Get();
-		else {
-			SynErr(n);
-			while (!StartOf(follow)) Get();
-		}
-	}
-	
-	boolean WeakSeparator (int n, int syFol, int repFol) {
-		int kind = la.kind;
-		if (kind == n) { Get(); return true; }
-		else if (StartOf(repFol)) return false;
-		else {
-			SynErr(n);
-			while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
-				Get();
-				kind = la.kind;
-			}
-			return StartOf(syFol);
-		}
-	}
-	
-	QIRNode  QIR() {
-		QIRNode  res;
-		QIRNode expr = Or();
-		res = expr; 
-		return res;
-	}
-
-	QIRNode  Or() {
-		QIRNode  res;
-		res = And();
-		final Token srcToken = t; 
-		while (la.kind == 5) {
-			Get();
-			QIRNode right = And();
-			res = QIROrNodeGen.create(srcFromToken(srcToken), res, right); 
-		}
-		return res;
-	}
-
-	QIRNode  And() {
-		QIRNode  res;
-		res = Equal();
-		final Token srcToken = t; 
-		while (la.kind == 6) {
-			Get();
-			QIRNode right = Equal();
-			res = QIRAndNodeGen.create(srcFromToken(srcToken), res, right); 
-		}
-		return res;
-	}
-
-	QIRNode  Equal() {
-		QIRNode  res;
-		res = Lower();
-		final Token srcToken = t; 
-		while (la.kind == 7) {
-			Get();
-			QIRNode right = Lower();
-			res = QIREqualNodeGen.create(srcFromToken(srcToken), res, right); 
-		}
-		return res;
-	}
-
-	QIRNode  Lower() {
-		QIRNode  res;
-		res = Plus();
-		final Token srcToken = t; 
-		while (la.kind == 8 || la.kind == 9) {
-			if (la.kind == 8) {
-				Get();
-			} else {
-				Get();
-			}
-			final Token opToken = t; 
-			QIRNode right = Plus();
-			switch (opToken.val) {
-			case "<":
-			res = QIRLowerThanNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			default:
-			res = QIRLowerOrEqualNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			} 
-		}
-		return res;
-	}
-
-	QIRNode  Plus() {
-		QIRNode  res;
-		res = Star();
-		final Token srcToken = t; 
-		while (la.kind == 10 || la.kind == 11) {
-			if (la.kind == 10) {
-				Get();
-			} else {
-				Get();
-			}
-			final Token opToken = t; 
-			QIRNode right = Star();
-			switch (opToken.val) {
-			case "+":
-			res = QIRPlusNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			default:
-			res = QIRMinusNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			} 
-		}
-		return res;
-	}
-
-	QIRNode  Star() {
-		QIRNode  res;
-		res = Not();
-		final Token srcToken = t; 
-		while (la.kind == 12 || la.kind == 13 || la.kind == 14) {
-			if (la.kind == 12) {
-				Get();
-			} else if (la.kind == 13) {
-				Get();
-			} else {
-				Get();
-			}
-			final Token opToken = t; 
-			QIRNode right = Not();
-			switch (opToken.val) {
-			case "*":
-			res = QIRStarNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			case "/":
-			res = QIRDivNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			default:
-			res = QIRModNodeGen.create(srcFromToken(srcToken), res, right);
-			break;
-			} 
-		}
-		return res;
-	}
-
-	QIRNode  Not() {
-		QIRNode  res;
-		final Token srcToken = t;
-		int nots = 0; 
-		while (la.kind == 15) {
-			Get();
-			nots++; 
-		}
-		res = Application();
-		while (nots-- > 0)
-		res = QIRNotNodeGen.create(srcFromToken(srcToken), res); 
-		return res;
-	}
-
-	QIRNode  Application() {
-		QIRNode  res;
-		res = Tupledestr();
-		final Token srcToken = t; 
-		while (la.kind == 16) {
-			Get();
-			QIRNode right = Tupledestr();
-			res = new QIRApply(srcFromToken(srcToken), res, right); 
-		}
-		return res;
-	}
-
-	QIRNode  Tupledestr() {
-		QIRNode  res;
-		res = Expression();
-		final Token srcToken = t; 
-		while (la.kind == 17) {
-			Get();
-			Expect(1);
-			res = new QIRRdestr(srcFromToken(srcToken), res, t.val); 
-		}
-		return res;
-	}
-
-	QIRNode  Expression() {
-		QIRNode  res;
-		res = null; 
-		switch (la.kind) {
-		case 1: {
-			QIRVariable result = Variable();
-			res = result; 
-			break;
-		}
-		case 21: {
-			QIRLambda result = Lambda();
-			res = result; 
-			break;
-		}
-		case 25: {
-			QIRIf result = Ifexpr();
-			res = result; 
-			break;
-		}
-		case 28: {
-			QIRRecord result = Tuplecons();
-			res = result; 
-			break;
-		}
-		case 39: {
-			QIRList result = Listcons();
-			res = result; 
-			break;
-		}
-		case 41: {
-			QIRLdestr result = Listdestr();
-			res = result; 
-			break;
-		}
-		case 44: {
-			QIRExternal result = External();
-			res = result; 
-			break;
-		}
-		case 45: {
-			QIRTable result = Table();
-			res = result; 
-			break;
-		}
-		case 46: {
-			QIRBigNumber result = Bignumber();
-			res = result; 
-			break;
-		}
-		case 47: case 48: {
-			QIRBoolean result = Boolean();
-			res = result; 
-			break;
-		}
-		case 3: {
-			QIRNumber result = Number();
-			res = result; 
-			break;
-		}
-		case 4: {
-			QIRDouble result = Double();
-			res = result; 
-			break;
-		}
-		case 49: {
-			QIRNull result = Null();
-			res = result; 
-			break;
-		}
-		case 2: {
-			QIRString result = String();
-			res = result; 
-			break;
-		}
-		case 14: {
-			Get();
-			final Token srcToken = t;
-			final List<QIRNode> args = new ArrayList<>(); 
-			Expect(1);
-			final Token opName = t; 
-			Expect(18);
-			if (StartOf(1)) {
-				QIRNode arg = QIR();
-				args.add(arg); 
-				while (la.kind == 19) {
-					Get();
-					arg = QIR();
-					args.add(arg); 
-				}
-			}
-			res = new ExternalOperator(srcFromToken(srcToken), opName.val, args); 
-			break;
-		}
-		case 50: {
-			QIRProject result = Project();
-			res = result; 
-			break;
-		}
-		case 51: {
-			QIRScan result = Scan();
-			res = result; 
-			break;
-		}
-		case 52: {
-			QIRFilter result = Filter();
-			res = result; 
-			break;
-		}
-		case 53: {
-			QIRGroupBy result = Groupby();
-			res = result; 
-			break;
-		}
-		case 54: {
-			QIRSortBy result = Sortby();
-			res = result; 
-			break;
-		}
-		case 55: {
-			QIRJoin result = Join();
-			res = result; 
-			break;
-		}
-		case 56: {
-			QIRLeftJoin result = Leftjoin();
-			res = result; 
-			break;
-		}
-		case 57: {
-			QIRRightJoin result = Rightjoin();
-			res = result; 
-			break;
-		}
-		case 18: {
-			Get();
-			res = QIR();
-			Expect(20);
-			break;
-		}
-		default: SynErr(59); break;
-		}
-		return res;
-	}
-
-	QIRVariable  Variable() {
-		QIRVariable  res;
-		Expect(1);
-		res = new QIRVariable(srcFromToken(t), t.val); 
-		return res;
-	}
-
-	QIRLambda  Lambda() {
-		QIRLambda  res;
-		Expect(21);
-		final Token srcToken = t;
-		Token funName = null;
-		QIRType type = null; 
-		if (la.kind == 22) {
-			Get();
-			Expect(1);
-			funName = t; 
-		}
-		if (la.kind == 23) {
-			Get();
-			type = Type();
-		}
-		QIRVariable var = Variable();
-		Expect(24);
-		QIRNode body = QIR();
-		res = new QIRLambda(srcFromToken(srcToken), funName == null ? null : funName.val, var, body, new FrameDescriptor());
-		if (type != null)
-		res.setType(type, QIRDefaultTypeSystemVisitor.class);
-		
-		return res;
-	}
-
-	QIRIf  Ifexpr() {
-		QIRIf  res;
-		Expect(25);
-		final Token srcToken = t; 
-		QIRNode cond = QIR();
-		Expect(26);
-		QIRNode thenNode = QIR();
-		Expect(27);
-		QIRNode elseNode = QIR();
-		res = new QIRIf(srcFromToken(srcToken), cond, thenNode, elseNode); 
-		return res;
-	}
-
-	QIRRecord  Tuplecons() {
-		QIRRecord  res;
-		Expect(28);
-		res = QIRRnil.getInstance();
-		final Token srcToken = t;
-		Token idToken;
-		QIRType type = null; 
-		if (la.kind == 1) {
-			Get();
-			idToken = t; 
-			Expect(29);
-			QIRNode value = QIR();
-			res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); 
-			while (la.kind == 30) {
-				Get();
-				Expect(1);
-				idToken = t; 
-				Expect(29);
-				value = QIR();
-				res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); 
-			}
-		}
-		Expect(31);
-		if (la.kind == 23) {
-			Get();
-			type = RecordType();
-		}
-		if (type != null)
-		res.setType(type, QIRDefaultTypeSystemVisitor.class); 
-		return res;
-	}
-
-	QIRList  Listcons() {
-		QIRList  res;
-		Expect(39);
-		res = QIRLnil.getInstance();
-		QIRType type = null;
-		final Token srcToken = t; 
-		if (StartOf(1)) {
-			QIRNode value = QIR();
-			res = new QIRLcons(srcFromToken(srcToken), value, res); 
-			while (la.kind == 30) {
-				Get();
-				value = QIR();
-				res = new QIRLcons(srcFromToken(srcToken), value, res); 
-			}
-		}
-		Expect(40);
-		if (la.kind == 23) {
-			Get();
-			type = ListType();
-		}
-		if (type != null)
-		res.setType(type, QIRDefaultTypeSystemVisitor.class); 
-		return res;
-	}
-
-	QIRLdestr  Listdestr() {
-		QIRLdestr  res;
-		Expect(41);
-		final Token srcToken = t; 
-		QIRNode list = QIR();
-		Expect(42);
-		Expect(43);
-		Expect(24);
-		QIRNode ifEmpty = QIR();
-		Expect(27);
-		Expect(24);
-		QIRNode handler = QIR();
-		Expect(20);
-		res = new QIRLdestr(srcFromToken(srcToken), list, ifEmpty, handler); 
-		return res;
-	}
-
-	QIRExternal  External() {
-		QIRExternal  res;
-		Expect(44);
-		final Token srcToken = t; 
-		Expect(1);
-		final Token eName = t; 
-		Expect(20);
-		res = new QIRExternal(srcFromToken(srcToken), eName.val); 
-		return res;
-	}
-
-	QIRTable  Table() {
-		QIRTable  res;
-		Expect(45);
-		final Token srcToken = t; 
-		QIRNode tableName = QIR();
-		Expect(19);
-		QIRNode dbName = QIR();
-		Expect(19);
-		QIRNode configFile = QIR();
-		Expect(19);
-		QIRNode schemaName = QIR();
-		Expect(20);
-		res = new QIRTable(srcFromToken(srcToken), tableName, dbName, configFile, schemaName); 
-		return res;
-	}
-
-	QIRBigNumber  Bignumber() {
-		QIRBigNumber  res;
-		Expect(46);
-		final Token srcToken = t; 
-		Expect(3);
-		final Token number = t; 
-		Expect(20);
-		res = new QIRBigNumber(srcFromToken(srcToken), new BigInteger(number.val)); 
-		return res;
-	}
-
-	QIRBoolean  Boolean() {
-		QIRBoolean  res;
-		res = null; 
-		if (la.kind == 47) {
-			Get();
-			res = QIRBoolean.TRUE; 
-		} else if (la.kind == 48) {
-			Get();
-			res = QIRBoolean.FALSE; 
-		} else SynErr(60);
-		return res;
-	}
-
-	QIRNumber  Number() {
-		QIRNumber  res;
-		Expect(3);
-		res = new QIRNumber(srcFromToken(t), Long.parseLong(t.val)); 
-		return res;
-	}
-
-	QIRDouble  Double() {
-		QIRDouble  res;
-		Expect(4);
-		res = new QIRDouble(srcFromToken(t), Double.parseDouble(t.val)); 
-		return res;
-	}
-
-	QIRNull  Null() {
-		QIRNull  res;
-		Expect(49);
-		res = QIRNull.getInstance(); 
-		return res;
-	}
-
-	QIRString  String() {
-		QIRString  res;
-		Expect(2);
-		res = new QIRString(srcFromToken(t), t.val); 
-		return res;
-	}
-
-	QIRProject  Project() {
-		QIRProject  res;
-		Expect(50);
-		final Token srcToken = t; 
-		QIRNode formatter = QIR();
-		Expect(19);
-		QIRNode child = QIR();
-		Expect(20);
-		res = new QIRProject(srcFromToken(srcToken), formatter, child); 
-		return res;
-	}
-
-	QIRScan  Scan() {
-		QIRScan  res;
-		Expect(51);
-		final Token srcToken = t; 
-		QIRNode child = QIR();
-		Expect(20);
-		res = new QIRScan(srcFromToken(srcToken), child); 
-		return res;
-	}
-
-	QIRFilter  Filter() {
-		QIRFilter  res;
-		Expect(52);
-		final Token srcToken = t; 
-		QIRNode filter = QIR();
-		Expect(19);
-		QIRNode child = QIR();
-		Expect(20);
-		res = new QIRFilter(srcFromToken(srcToken), filter, child); 
-		return res;
-	}
-
-	QIRGroupBy  Groupby() {
-		QIRGroupBy  res;
-		Expect(53);
-		final Token srcToken = t; 
-		QIRNode group = QIR();
-		Expect(19);
-		QIRNode child = QIR();
-		Expect(20);
-		res = new QIRGroupBy(srcFromToken(srcToken), group, child); 
-		return res;
-	}
-
-	QIRSortBy  Sortby() {
-		QIRSortBy  res;
-		Expect(54);
-		final Token srcToken = t; 
-		QIRNode sort = QIR();
-		Expect(19);
-		QIRNode isAscending = QIR();
-		Expect(19);
-		QIRNode child = QIR();
-		Expect(20);
-		res = new QIRSortBy(srcFromToken(srcToken), sort, isAscending, child); 
-		return res;
-	}
-
-	QIRJoin  Join() {
-		QIRJoin  res;
-		Expect(55);
-		final Token srcToken = t; 
-		QIRNode filter = QIR();
-		Expect(19);
-		QIRNode left = QIR();
-		Expect(19);
-		QIRNode right = QIR();
-		Expect(20);
-		res = new QIRJoin(srcFromToken(srcToken), filter, left, right); 
-		return res;
-	}
-
-	QIRLeftJoin  Leftjoin() {
-		QIRLeftJoin  res;
-		Expect(56);
-		final Token srcToken = t; 
-		QIRNode filter = QIR();
-		Expect(19);
-		QIRNode left = QIR();
-		Expect(19);
-		QIRNode right = QIR();
-		Expect(20);
-		res = new QIRLeftJoin(srcFromToken(srcToken), filter, left, right); 
-		return res;
-	}
-
-	QIRRightJoin  Rightjoin() {
-		QIRRightJoin  res;
-		Expect(57);
-		final Token srcToken = t; 
-		QIRNode filter = QIR();
-		Expect(19);
-		QIRNode left = QIR();
-		Expect(19);
-		QIRNode right = QIR();
-		Expect(20);
-		res = new QIRRightJoin(srcFromToken(srcToken), filter, left, right); 
-		return res;
-	}
-
-	QIRType  Type() {
-		QIRType  res;
-		res = null; 
-		QIRType first = NonFunctionType();
-		final List<QIRType> types = new ArrayList<>();
-		types.add(first); 
-		while (la.kind == 24) {
-			Get();
-			QIRType type = NonFunctionType();
-			types.add(type); 
-		}
-		res = types.size() == 1 ? first : new QIRFunctionType(types.subList(0, types.size() - 1).toArray(new QIRType[types.size() - 1]), types.get(types.size() - 1)); 
-		return res;
-	}
-
-	QIRRecordType  RecordType() {
-		QIRRecordType  res;
-		Expect(28);
-		final Map<String, QIRType> types = new HashMap<>(); 
-		if (la.kind == 1) {
-			Get();
-			Token idToken = t; 
-			Expect(23);
-			QIRType type = Type();
-			types.put(idToken.val, type); 
-			while (la.kind == 30) {
-				Get();
-				Expect(1);
-				idToken = t; 
-				Expect(23);
-				type = Type();
-				types.put(idToken.val, type); 
-			}
-		}
-		Expect(31);
-		res = new QIRRecordType(types); 
-		return res;
-	}
-
-	QIRType  NonFunctionType() {
-		QIRType  res;
-		res = null; 
-		if (StartOf(2)) {
-			res = ConstantType();
-		} else if (la.kind == 28) {
-			res = RecordType();
-		} else if (la.kind == 38) {
-			res = ListType();
-		} else if (la.kind == 18) {
-			Get();
-			res = Type();
-			Expect(20);
-		} else SynErr(61);
-		return res;
-	}
-
-	QIRType  ConstantType() {
-		QIRType  res;
-		res = null; 
-		switch (la.kind) {
-		case 32: {
-			Get();
-			res = QIRAnyType.getInstance(); 
-			break;
-		}
-		case 33: {
-			Get();
-			res = QIRNumberType.getInstance(); 
-			break;
-		}
-		case 34: {
-			Get();
-			res = QIRBigNumberType.getInstance(); 
-			break;
-		}
-		case 35: {
-			Get();
-			res = QIRDoubleType.getInstance(); 
-			break;
-		}
-		case 36: {
-			Get();
-			res = QIRBooleanType.getInstance(); 
-			break;
-		}
-		case 37: {
-			Get();
-			res = QIRStringType.getInstance(); 
-			break;
-		}
-		default: SynErr(62); break;
-		}
-		return res;
-	}
-
-	QIRListType  ListType() {
-		QIRListType  res;
-		Expect(38);
-		Expect(39);
-		QIRType type = Type();
-		Expect(40);
-		res = new QIRListType(type); 
-		return res;
-	}
-
-
-
-	public QIRNode Parse() {
-		la = new Token();
-		la.val = "";		
-		Get();
-		final QIRNode res =
-		QIR();
-		Expect(0);
-
-		return res;
-	}
-
-	private static final boolean[][] set = {
-		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x},
-		{_x,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_T,_x, _x,_T,_x,_x, _x,_T,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_T,_x,_x, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_x,_x},
-		{_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}
-
-	};
-
-	private SourceSection srcFromToken(Token token) {
-        return source.createSection(token.charPos, token.val.length());
-    }
-    
-    public static QIRNode parseQIR(final Source source) {
-		return new Parser(new Scanner(source.getInputStream()), source).Parse();
-    }
-} // end Parser
-
-
-class Errors {
-	public int count = 0;                                    // number of errors detected
-	public java.io.PrintStream errorStream = System.out;     // error messages go to this stream
-	public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-	
-	protected void printMsg(int line, int column, String msg) {
-		StringBuffer b = new StringBuffer(errMsgFormat);
-		int pos = b.indexOf("{0}");
-		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, line); }
-		pos = b.indexOf("{1}");
-		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, column); }
-		pos = b.indexOf("{2}");
-		if (pos >= 0) b.replace(pos, pos+3, msg);
-		errorStream.println(b.toString());
-	}
-	
-	public void SynErr (int line, int col, int n) {
-		String s;
-		switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "stringLiteral expected"; break;
-			case 3: s = "numberLiteral expected"; break;
-			case 4: s = "doubleLiteral expected"; break;
-			case 5: s = "\"||\" expected"; break;
-			case 6: s = "\"&&\" expected"; break;
-			case 7: s = "\"==\" expected"; break;
-			case 8: s = "\"<\" expected"; break;
-			case 9: s = "\"<=\" expected"; break;
-			case 10: s = "\"+\" expected"; break;
-			case 11: s = "\"-\" expected"; break;
-			case 12: s = "\"*\" expected"; break;
-			case 13: s = "\"/\" expected"; break;
-			case 14: s = "\"%\" expected"; break;
-			case 15: s = "\"!\" expected"; break;
-			case 16: s = "\"@\" expected"; break;
-			case 17: s = "\".\" expected"; break;
-			case 18: s = "\"(\" expected"; break;
-			case 19: s = "\",\" expected"; break;
-			case 20: s = "\")\" expected"; break;
-			case 21: s = "\"fun\" expected"; break;
-			case 22: s = "\"#\" expected"; break;
-			case 23: s = "\":\" expected"; break;
-			case 24: s = "\"->\" expected"; break;
-			case 25: s = "\"if\" expected"; break;
-			case 26: s = "\"then\" expected"; break;
-			case 27: s = "\"else\" expected"; break;
-			case 28: s = "\"{\" expected"; break;
-			case 29: s = "\"=\" expected"; break;
-			case 30: s = "\";\" expected"; break;
-			case 31: s = "\"}\" expected"; break;
-			case 32: s = "\"any\" expected"; break;
-			case 33: s = "\"int\" expected"; break;
-			case 34: s = "\"big_int\" expected"; break;
-			case 35: s = "\"double\" expected"; break;
-			case 36: s = "\"bool\" expected"; break;
-			case 37: s = "\"string\" expected"; break;
-			case 38: s = "\"list\" expected"; break;
-			case 39: s = "\"[\" expected"; break;
-			case 40: s = "\"]\" expected"; break;
-			case 41: s = "\"match\" expected"; break;
-			case 42: s = "\"with\" expected"; break;
-			case 43: s = "\"empty\" expected"; break;
-			case 44: s = "\"External(\" expected"; break;
-			case 45: s = "\"Table(\" expected"; break;
-			case 46: s = "\"BigNumber(\" expected"; break;
-			case 47: s = "\"true\" expected"; break;
-			case 48: s = "\"false\" expected"; break;
-			case 49: s = "\"NULL\" expected"; break;
-			case 50: s = "\"%Project(\" expected"; break;
-			case 51: s = "\"%Scan(\" expected"; break;
-			case 52: s = "\"%Filter(\" expected"; break;
-			case 53: s = "\"%GroupBy(\" expected"; break;
-			case 54: s = "\"%SortBy(\" expected"; break;
-			case 55: s = "\"%Join(\" expected"; break;
-			case 56: s = "\"%LeftJoin(\" expected"; break;
-			case 57: s = "\"%RightJoin(\" expected"; break;
-			case 58: s = "??? expected"; break;
-			case 59: s = "invalid Expression"; break;
-			case 60: s = "invalid Boolean"; break;
-			case 61: s = "invalid NonFunctionType"; break;
-			case 62: s = "invalid ConstantType"; break;
-			default: s = "error " + n; break;
-		}
-		printMsg(line, col, s);
-		count++;
-	}
-
-	public void SemErr (int line, int col, String s) {	
-		printMsg(line, col, s);
-		count++;
-	}
-	
-	public void SemErr (String s) {
-		errorStream.println(s);
-		count++;
-	}
-	
-	public void Warning (int line, int col, String s) {	
-		printMsg(line, col, s);
-	}
-	
-	public void Warning (String s) {
-		errorStream.println(s);
-	}
-} // Errors
-
-
-class FatalError extends RuntimeException {
-	public static final long serialVersionUID = 1L;
-	public FatalError(String s) { super(s); }
-}
diff --git a/src/qir/parser/ParserTest.java b/src/qir/parser/ParserTest.java
index bf9b17f0478ee4885e15745bb7193da477e5d186..2d82b8af612c46c322115b6ed76a654e08a59548 100644
--- a/src/qir/parser/ParserTest.java
+++ b/src/qir/parser/ParserTest.java
@@ -1,7 +1,8 @@
 package qir.parser;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
@@ -12,8 +13,8 @@ import qir.ast.QIRNode;
 
 public class ParserTest {
     public static final void main(final String[] args) throws RuntimeException, IOException {
-        final Source source = Source.newBuilder(new File(args[0])).mimeType(QIRLanguage.MIME_TYPE).name("QIR").build();
-        final QIRNode res = Parser.parseQIR(source);
+        final Source source = Source.newBuilder("QIR", new String(Files.readAllBytes(Paths.get(args[0]))), "Test parser").mimeType(QIRLanguage.MIME_TYPE).name("QIR").build();
+        final QIRNode res = qirParser.parseQIR(source);
         System.out.println(res);
         System.out.println(res.executeGeneric(Truffle.getRuntime().createVirtualFrame(new Object[]{}, new FrameDescriptor())));
     }
diff --git a/src/qir/parser/Scanner.java b/src/qir/parser/Scanner.java
deleted file mode 100644
index e379b5987a5cb12a3ecb8a8be1232efc6f385523..0000000000000000000000000000000000000000
--- a/src/qir/parser/Scanner.java
+++ /dev/null
@@ -1,906 +0,0 @@
-package qir.parser;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.Map;
-import java.util.HashMap;
-
-class Token {
-	public int kind;    // token kind
-	public int pos;     // token position in bytes in the source text (starting at 0)
-	public int charPos; // token position in characters in the source text (starting at 0)
-	public int col;     // token column (starting at 1)
-	public int line;    // token line (starting at 1)
-	public String val;  // token value
-	public Token next;  // ML 2005-03-11 Peek tokens are kept in linked list
-}
-
-//-----------------------------------------------------------------------------------
-// Buffer
-//-----------------------------------------------------------------------------------
-class Buffer {
-	// This Buffer supports the following cases:
-	// 1) seekable stream (file)
-	//    a) whole stream in buffer
-	//    b) part of stream in buffer
-	// 2) non seekable stream (network, console)
-
-	public static final int EOF = Character.MAX_VALUE + 1;
-	private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
-	private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
-	private byte[] buf;   // input buffer
-	private int bufStart; // position of first byte in buffer relative to input stream
-	private int bufLen;   // length of buffer
-	private int fileLen;  // length of input stream (may change if stream is no file)
-	private int bufPos;      // current position in buffer
-	private RandomAccessFile file; // input stream (seekable)
-	private InputStream stream; // growing input stream (e.g.: console, network)
-
-	public Buffer(InputStream s) {
-		stream = s;
-		fileLen = bufLen = bufStart = bufPos = 0;
-		buf = new byte[MIN_BUFFER_LENGTH];
-	}
-
-	public Buffer(String fileName) {
-		try {
-			file = new RandomAccessFile(fileName, "r");
-			fileLen = (int) file.length();
-			bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
-			buf = new byte[bufLen];
-			bufStart = Integer.MAX_VALUE; // nothing in buffer so far
-			if (fileLen > 0) setPos(0); // setup buffer to position 0 (start)
-			else bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
-			if (bufLen == fileLen) Close();
-		} catch (IOException e) {
-			throw new FatalError("Could not open file " + fileName);
-		}
-	}
-
-	// don't use b after this call anymore
-	// called in UTF8Buffer constructor
-	protected Buffer(Buffer b) {
-		buf = b.buf;
-		bufStart = b.bufStart;
-		bufLen = b.bufLen;
-		fileLen = b.fileLen;
-		bufPos = b.bufPos;
-		file = b.file;
-		stream = b.stream;
-		// keep finalize from closing the file
-		b.file = null;
-	}
-
-	@Override
-	protected void finalize() throws Throwable {
-		super.finalize();
-		Close();
-	}
-
-	protected void Close() {
-		if (file != null) {
-			try {
-				file.close();
-				file = null;
-			} catch (IOException e) {
-				throw new FatalError(e.getMessage());
-			}
-		}
-	}
-
-	public int Read() {
-		if (bufPos < bufLen) {
-			return buf[bufPos++] & 0xff;  // mask out sign bits
-		} else if (getPos() < fileLen) {
-			setPos(getPos());         // shift buffer start to pos
-			return buf[bufPos++] & 0xff; // mask out sign bits
-		} else if (stream != null && ReadNextStreamChunk() > 0) {
-			return buf[bufPos++] & 0xff;  // mask out sign bits
-		} else {
-			return EOF;
-		}
-	}
-
-	public int Peek() {
-		int curPos = getPos();
-		int ch = Read();
-		setPos(curPos);
-		return ch;
-	}
-
-	// beg .. begin, zero-based, inclusive, in byte
-	// end .. end, zero-based, exclusive, in byte
-	public String GetString(int beg, int end) {
-		int len = 0;
-		char[] buff = new char[end - beg];
-		int oldPos = getPos();
-		setPos(beg);
-		while (getPos() < end) buff[len++] = (char) Read();
-		setPos(oldPos);
-		return new String(buff, 0, len);
-	}
-
-	public int getPos() {
-		return bufPos + bufStart;
-	}
-
-	public void setPos(int value) {
-		if (value >= fileLen && stream != null) {
-			// Wanted position is after buffer and the stream
-			// is not seek-able e.g. network or console,
-			// thus we have to read the stream manually till
-			// the wanted position is in sight.
-			while (value >= fileLen && ReadNextStreamChunk() > 0){}
-		}
-
-		if (value < 0 || value > fileLen) {
-			throw new FatalError("buffer out of bounds access, position: " + value);
-		}
-
-		if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
-			bufPos = value - bufStart;
-		} else if (file != null) { // must be swapped in
-			try {
-				file.seek(value);
-				bufLen = file.read(buf);
-				bufStart = value; bufPos = 0;
-			} catch(IOException e) {
-				throw new FatalError(e.getMessage());
-			}
-		} else {
-			// set the position to the end of the file, Pos will return fileLen.
-			bufPos = fileLen - bufStart;
-		}
-	}
-	
-	// Read the next chunk of bytes from the stream, increases the buffer
-	// if needed and updates the fields fileLen and bufLen.
-	// Returns the number of bytes read.
-	private int ReadNextStreamChunk() {
-		int free = buf.length - bufLen;
-		if (free == 0) {
-			// in the case of a growing input stream
-			// we can neither seek in the stream, nor can we
-			// foresee the maximum length, thus we must adapt
-			// the buffer size on demand.
-			byte[] newBuf = new byte[bufLen * 2];
-			System.arraycopy(buf, 0, newBuf, 0, bufLen);
-			buf = newBuf;
-			free = bufLen;
-		}
-		
-		int read;
-		try { read = stream.read(buf, bufLen, free); }
-		catch (IOException ioex) { throw new FatalError(ioex.getMessage()); }
-		
-		if (read > 0) {
-			fileLen = bufLen = (bufLen + read);
-			return read;
-		}
-		// end of stream reached
-		return 0;
-	}
-}
-
-//-----------------------------------------------------------------------------------
-// UTF8Buffer
-//-----------------------------------------------------------------------------------
-class UTF8Buffer extends Buffer {
-	UTF8Buffer(Buffer b) { super(b); }
-
-	@Override
-	public int Read() {
-		int ch;
-		do {
-			ch = super.Read();
-			// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
-		} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
-		if (ch < 128 || ch == EOF) {
-			// nothing to do, first 127 chars are the same in ascii and utf8
-			// 0xxxxxxx or end of file character
-		} else if ((ch & 0xF0) == 0xF0) {
-			// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-			int c1 = ch & 0x07; ch = super.Read();
-			int c2 = ch & 0x3F; ch = super.Read();
-			int c3 = ch & 0x3F; ch = super.Read();
-			int c4 = ch & 0x3F;
-			ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
-		} else if ((ch & 0xE0) == 0xE0) {
-			// 1110xxxx 10xxxxxx 10xxxxxx
-			int c1 = ch & 0x0F; ch = super.Read();
-			int c2 = ch & 0x3F; ch = super.Read();
-			int c3 = ch & 0x3F;
-			ch = (((c1 << 6) | c2) << 6) | c3;
-		} else if ((ch & 0xC0) == 0xC0) {
-			// 110xxxxx 10xxxxxx
-			int c1 = ch & 0x1F; ch = super.Read();
-			int c2 = ch & 0x3F;
-			ch = (c1 << 6) | c2;
-		}
-		return ch;
-	}
-}
-
-//-----------------------------------------------------------------------------------
-// StartStates  -- maps characters to start states of tokens
-//-----------------------------------------------------------------------------------
-class StartStates {
-	private static class Elem {
-		public int key, val;
-		public Elem next;
-		public Elem(int key, int val) { this.key = key; this.val = val; }
-	}
-
-	private Elem[] tab = new Elem[128];
-
-	public void set(int key, int val) {
-		Elem e = new Elem(key, val);
-		int k = key % 128;
-		e.next = tab[k]; tab[k] = e;
-	}
-
-	public int state(int key) {
-		Elem e = tab[key % 128];
-		while (e != null && e.key != key) e = e.next;
-		return e == null ? 0: e.val;
-	}
-}
-
-//-----------------------------------------------------------------------------------
-// Scanner
-//-----------------------------------------------------------------------------------
-public class Scanner {
-	static final char EOL = '\n';
-	static final int  eofSym = 0;
-	static final int maxT = 58;
-	static final int noSym = 58;
-
-
-	public Buffer buffer; // scanner buffer
-
-	Token t;           // current token
-	int ch;            // current input character
-	int pos;           // byte position of current character
-	int charPos;       // position by unicode characters starting with 0
-	int col;           // column number of current character
-	int line;          // line number of current character
-	int oldEols;       // EOLs that appeared in a comment;
-	static final StartStates start; // maps initial token character to start state
-	static final Map<String, Integer> literals;      // maps literal strings to literal kinds
-
-	Token tokens;      // list of tokens already peeked (first token is a dummy)
-	Token pt;          // current peek token
-	
-	char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
-	int tlen;          // length of current token
-
-
-	static {
-		start = new StartStates();
-		literals = new HashMap<>();
-		for (int i = 65; i <= 65; ++i) start.set(i, 1);
-		for (int i = 67; i <= 68; ++i) start.set(i, 1);
-		for (int i = 70; i <= 83; ++i) start.set(i, 1);
-		for (int i = 85; i <= 90; ++i) start.set(i, 1);
-		for (int i = 97; i <= 122; ++i) start.set(i, 1);
-		for (int i = 49; i <= 57; ++i) start.set(i, 10);
-		start.set(48, 11); 
-		start.set(34, 2); 
-		start.set(45, 96); 
-		start.set(124, 13); 
-		start.set(38, 15); 
-		start.set(61, 97); 
-		start.set(60, 98); 
-		start.set(43, 19); 
-		start.set(42, 20); 
-		start.set(47, 21); 
-		start.set(37, 99); 
-		start.set(33, 22); 
-		start.set(64, 23); 
-		start.set(46, 24); 
-		start.set(40, 25); 
-		start.set(44, 26); 
-		start.set(41, 27); 
-		start.set(35, 28); 
-		start.set(58, 29); 
-		start.set(123, 31); 
-		start.set(59, 32); 
-		start.set(125, 33); 
-		start.set(91, 34); 
-		start.set(93, 35); 
-		start.set(69, 100); 
-		start.set(84, 101); 
-		start.set(66, 102); 
-		start.set(Buffer.EOF, -1);
-		literals.put("fun", new Integer(21));
-		literals.put("if", new Integer(25));
-		literals.put("then", new Integer(26));
-		literals.put("else", new Integer(27));
-		literals.put("any", new Integer(32));
-		literals.put("int", new Integer(33));
-		literals.put("big_int", new Integer(34));
-		literals.put("double", new Integer(35));
-		literals.put("bool", new Integer(36));
-		literals.put("string", new Integer(37));
-		literals.put("list", new Integer(38));
-		literals.put("match", new Integer(41));
-		literals.put("with", new Integer(42));
-		literals.put("empty", new Integer(43));
-		literals.put("true", new Integer(47));
-		literals.put("false", new Integer(48));
-		literals.put("NULL", new Integer(49));
-
-	}
-	
-	public Scanner (String fileName) {
-		buffer = new Buffer(fileName);
-		Init();
-	}
-	
-	public Scanner(InputStream s) {
-		buffer = new Buffer(s);
-		Init();
-	}
-	
-	void Init () {
-		pos = -1; line = 1; col = 0; charPos = -1;
-		oldEols = 0;
-		NextCh();
-		if (ch == 0xEF) { // check optional byte order mark for UTF-8
-			NextCh(); int ch1 = ch;
-			NextCh(); int ch2 = ch;
-			if (ch1 != 0xBB || ch2 != 0xBF) {
-				throw new FatalError("Illegal byte order mark at start of file");
-			}
-			buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
-			NextCh();
-		}
-		pt = tokens = new Token();  // first token is a dummy
-	}
-	
-	void NextCh() {
-		if (oldEols > 0) { ch = EOL; oldEols--; }
-		else {
-			pos = buffer.getPos();
-			// buffer reads unicode chars, if UTF8 has been detected
-			ch = buffer.Read(); col++; charPos++;
-			// replace isolated '\r' by '\n' in order to make
-			// eol handling uniform across Windows, Unix and Mac
-			if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
-			if (ch == EOL) { line++; col = 0; }
-		}
-
-	}
-	
-	void AddCh() {
-		if (tlen >= tval.length) {
-			char[] newBuf = new char[2 * tval.length];
-			System.arraycopy(tval, 0, newBuf, 0, tval.length);
-			tval = newBuf;
-		}
-		if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch; 
-
-			NextCh();
-		}
-
-	}
-	
-
-	boolean Comment0() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '/') {
-			NextCh();
-			for(;;) {
-				if (ch == 10) {
-					level--;
-					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-					NextCh();
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
-
-	boolean Comment1() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '*') {
-			NextCh();
-			for(;;) {
-				if (ch == '*') {
-					NextCh();
-					if (ch == '/') {
-						level--;
-						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-						NextCh();
-					}
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
-
-
-	void CheckLiteral() {
-		String val = t.val;
-
-		Object kind = literals.get(val);
-		if (kind != null) {
-			t.kind = ((Integer) kind).intValue();
-		}
-	}
-
-	Token NextToken() {
-		while (ch == ' ' ||
-			ch >= 9 && ch <= 10 || ch == 13
-		) NextCh();
-		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
-		int recKind = noSym;
-		int recEnd = pos;
-		t = new Token();
-		t.pos = pos; t.col = col; t.line = line; t.charPos = charPos;
-		int state = start.state(ch);
-		tlen = 0; AddCh();
-
-		loop: for (;;) {
-			switch (state) {
-				case -1: { t.kind = eofSym; break loop; } // NextCh already done 
-				case 0: {
-					if (recKind != noSym) {
-						tlen = recEnd - t.pos;
-						SetScannerBehindT();
-					}
-					t.kind = recKind; break loop;
-				} // NextCh already done
-				case 1:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 2:
-					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
-					else if (ch == '"') {AddCh(); state = 3; break;}
-					else {state = 0; break;}
-				case 3:
-					{t.kind = 2; break loop;}
-				case 4:
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
-					else if (ch == '.') {AddCh(); state = 5; break;}
-					else {state = 0; break;}
-				case 5:
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 6; break;}
-					else {state = 0; break;}
-				case 6:
-					recEnd = pos; recKind = 4;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 6; break;}
-					else {t.kind = 4; break loop;}
-				case 7:
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 7; break;}
-					else if (ch == '.') {AddCh(); state = 8; break;}
-					else {state = 0; break;}
-				case 8:
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 9; break;}
-					else {state = 0; break;}
-				case 9:
-					recEnd = pos; recKind = 4;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 9; break;}
-					else {t.kind = 4; break loop;}
-				case 10:
-					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 10; break;}
-					else if (ch == '.') {AddCh(); state = 5; break;}
-					else {t.kind = 3; break loop;}
-				case 11:
-					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
-					else if (ch == '.') {AddCh(); state = 5; break;}
-					else {t.kind = 3; break loop;}
-				case 12:
-					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 12; break;}
-					else if (ch == '.') {AddCh(); state = 8; break;}
-					else {t.kind = 3; break loop;}
-				case 13:
-					if (ch == '|') {AddCh(); state = 14; break;}
-					else {state = 0; break;}
-				case 14:
-					{t.kind = 5; break loop;}
-				case 15:
-					if (ch == '&') {AddCh(); state = 16; break;}
-					else {state = 0; break;}
-				case 16:
-					{t.kind = 6; break loop;}
-				case 17:
-					{t.kind = 7; break loop;}
-				case 18:
-					{t.kind = 9; break loop;}
-				case 19:
-					{t.kind = 10; break loop;}
-				case 20:
-					{t.kind = 12; break loop;}
-				case 21:
-					{t.kind = 13; break loop;}
-				case 22:
-					{t.kind = 15; break loop;}
-				case 23:
-					{t.kind = 16; break loop;}
-				case 24:
-					{t.kind = 17; break loop;}
-				case 25:
-					{t.kind = 18; break loop;}
-				case 26:
-					{t.kind = 19; break loop;}
-				case 27:
-					{t.kind = 20; break loop;}
-				case 28:
-					{t.kind = 22; break loop;}
-				case 29:
-					{t.kind = 23; break loop;}
-				case 30:
-					{t.kind = 24; break loop;}
-				case 31:
-					{t.kind = 28; break loop;}
-				case 32:
-					{t.kind = 30; break loop;}
-				case 33:
-					{t.kind = 31; break loop;}
-				case 34:
-					{t.kind = 39; break loop;}
-				case 35:
-					{t.kind = 40; break loop;}
-				case 36:
-					{t.kind = 44; break loop;}
-				case 37:
-					{t.kind = 45; break loop;}
-				case 38:
-					{t.kind = 46; break loop;}
-				case 39:
-					if (ch == 'r') {AddCh(); state = 40; break;}
-					else {state = 0; break;}
-				case 40:
-					if (ch == 'o') {AddCh(); state = 41; break;}
-					else {state = 0; break;}
-				case 41:
-					if (ch == 'j') {AddCh(); state = 42; break;}
-					else {state = 0; break;}
-				case 42:
-					if (ch == 'e') {AddCh(); state = 43; break;}
-					else {state = 0; break;}
-				case 43:
-					if (ch == 'c') {AddCh(); state = 44; break;}
-					else {state = 0; break;}
-				case 44:
-					if (ch == 't') {AddCh(); state = 45; break;}
-					else {state = 0; break;}
-				case 45:
-					if (ch == '(') {AddCh(); state = 46; break;}
-					else {state = 0; break;}
-				case 46:
-					{t.kind = 50; break loop;}
-				case 47:
-					if (ch == 'a') {AddCh(); state = 48; break;}
-					else {state = 0; break;}
-				case 48:
-					if (ch == 'n') {AddCh(); state = 49; break;}
-					else {state = 0; break;}
-				case 49:
-					if (ch == '(') {AddCh(); state = 50; break;}
-					else {state = 0; break;}
-				case 50:
-					{t.kind = 51; break loop;}
-				case 51:
-					if (ch == 'i') {AddCh(); state = 52; break;}
-					else {state = 0; break;}
-				case 52:
-					if (ch == 'l') {AddCh(); state = 53; break;}
-					else {state = 0; break;}
-				case 53:
-					if (ch == 't') {AddCh(); state = 54; break;}
-					else {state = 0; break;}
-				case 54:
-					if (ch == 'e') {AddCh(); state = 55; break;}
-					else {state = 0; break;}
-				case 55:
-					if (ch == 'r') {AddCh(); state = 56; break;}
-					else {state = 0; break;}
-				case 56:
-					if (ch == '(') {AddCh(); state = 57; break;}
-					else {state = 0; break;}
-				case 57:
-					{t.kind = 52; break loop;}
-				case 58:
-					if (ch == 'r') {AddCh(); state = 59; break;}
-					else {state = 0; break;}
-				case 59:
-					if (ch == 'o') {AddCh(); state = 60; break;}
-					else {state = 0; break;}
-				case 60:
-					if (ch == 'u') {AddCh(); state = 61; break;}
-					else {state = 0; break;}
-				case 61:
-					if (ch == 'p') {AddCh(); state = 62; break;}
-					else {state = 0; break;}
-				case 62:
-					if (ch == 'B') {AddCh(); state = 63; break;}
-					else {state = 0; break;}
-				case 63:
-					if (ch == 'y') {AddCh(); state = 64; break;}
-					else {state = 0; break;}
-				case 64:
-					if (ch == '(') {AddCh(); state = 65; break;}
-					else {state = 0; break;}
-				case 65:
-					{t.kind = 53; break loop;}
-				case 66:
-					if (ch == 'r') {AddCh(); state = 67; break;}
-					else {state = 0; break;}
-				case 67:
-					if (ch == 't') {AddCh(); state = 68; break;}
-					else {state = 0; break;}
-				case 68:
-					if (ch == 'B') {AddCh(); state = 69; break;}
-					else {state = 0; break;}
-				case 69:
-					if (ch == 'y') {AddCh(); state = 70; break;}
-					else {state = 0; break;}
-				case 70:
-					if (ch == '(') {AddCh(); state = 71; break;}
-					else {state = 0; break;}
-				case 71:
-					{t.kind = 54; break loop;}
-				case 72:
-					if (ch == 'o') {AddCh(); state = 73; break;}
-					else {state = 0; break;}
-				case 73:
-					if (ch == 'i') {AddCh(); state = 74; break;}
-					else {state = 0; break;}
-				case 74:
-					if (ch == 'n') {AddCh(); state = 75; break;}
-					else {state = 0; break;}
-				case 75:
-					if (ch == '(') {AddCh(); state = 76; break;}
-					else {state = 0; break;}
-				case 76:
-					{t.kind = 55; break loop;}
-				case 77:
-					if (ch == 'e') {AddCh(); state = 78; break;}
-					else {state = 0; break;}
-				case 78:
-					if (ch == 'f') {AddCh(); state = 79; break;}
-					else {state = 0; break;}
-				case 79:
-					if (ch == 't') {AddCh(); state = 80; break;}
-					else {state = 0; break;}
-				case 80:
-					if (ch == 'J') {AddCh(); state = 81; break;}
-					else {state = 0; break;}
-				case 81:
-					if (ch == 'o') {AddCh(); state = 82; break;}
-					else {state = 0; break;}
-				case 82:
-					if (ch == 'i') {AddCh(); state = 83; break;}
-					else {state = 0; break;}
-				case 83:
-					if (ch == 'n') {AddCh(); state = 84; break;}
-					else {state = 0; break;}
-				case 84:
-					if (ch == '(') {AddCh(); state = 85; break;}
-					else {state = 0; break;}
-				case 85:
-					{t.kind = 56; break loop;}
-				case 86:
-					if (ch == 'i') {AddCh(); state = 87; break;}
-					else {state = 0; break;}
-				case 87:
-					if (ch == 'g') {AddCh(); state = 88; break;}
-					else {state = 0; break;}
-				case 88:
-					if (ch == 'h') {AddCh(); state = 89; break;}
-					else {state = 0; break;}
-				case 89:
-					if (ch == 't') {AddCh(); state = 90; break;}
-					else {state = 0; break;}
-				case 90:
-					if (ch == 'J') {AddCh(); state = 91; break;}
-					else {state = 0; break;}
-				case 91:
-					if (ch == 'o') {AddCh(); state = 92; break;}
-					else {state = 0; break;}
-				case 92:
-					if (ch == 'i') {AddCh(); state = 93; break;}
-					else {state = 0; break;}
-				case 93:
-					if (ch == 'n') {AddCh(); state = 94; break;}
-					else {state = 0; break;}
-				case 94:
-					if (ch == '(') {AddCh(); state = 95; break;}
-					else {state = 0; break;}
-				case 95:
-					{t.kind = 57; break loop;}
-				case 96:
-					recEnd = pos; recKind = 11;
-					if (ch >= '1' && ch <= '9') {AddCh(); state = 12; break;}
-					else if (ch == '0') {AddCh(); state = 7; break;}
-					else if (ch == '>') {AddCh(); state = 30; break;}
-					else {t.kind = 11; break loop;}
-				case 97:
-					recEnd = pos; recKind = 29;
-					if (ch == '=') {AddCh(); state = 17; break;}
-					else {t.kind = 29; break loop;}
-				case 98:
-					recEnd = pos; recKind = 8;
-					if (ch == '=') {AddCh(); state = 18; break;}
-					else {t.kind = 8; break loop;}
-				case 99:
-					recEnd = pos; recKind = 14;
-					if (ch == 'P') {AddCh(); state = 39; break;}
-					else if (ch == 'S') {AddCh(); state = 103; break;}
-					else if (ch == 'F') {AddCh(); state = 51; break;}
-					else if (ch == 'G') {AddCh(); state = 58; break;}
-					else if (ch == 'J') {AddCh(); state = 72; break;}
-					else if (ch == 'L') {AddCh(); state = 77; break;}
-					else if (ch == 'R') {AddCh(); state = 86; break;}
-					else {t.kind = 14; break loop;}
-				case 100:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'w' || ch >= 'y' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'x') {AddCh(); state = 104; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 101:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'b' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'a') {AddCh(); state = 105; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 102:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'h' || ch >= 'j' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'i') {AddCh(); state = 106; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 103:
-					if (ch == 'c') {AddCh(); state = 47; break;}
-					else if (ch == 'o') {AddCh(); state = 66; break;}
-					else {state = 0; break;}
-				case 104:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 's' || ch >= 'u' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 't') {AddCh(); state = 107; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 105:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == 'a' || ch >= 'c' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'b') {AddCh(); state = 108; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 106:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'f' || ch >= 'h' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'g') {AddCh(); state = 109; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 107:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'd' || ch >= 'f' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'e') {AddCh(); state = 110; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 108:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'k' || ch >= 'm' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'l') {AddCh(); state = 111; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 109:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'M' || ch >= 'O' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'N') {AddCh(); state = 112; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 110:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'q' || ch >= 's' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'r') {AddCh(); state = 113; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 111:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'd' || ch >= 'f' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'e') {AddCh(); state = 114; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 112:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 't' || ch >= 'v' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'u') {AddCh(); state = 115; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 113:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'm' || ch >= 'o' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'n') {AddCh(); state = 116; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 114:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == '(') {AddCh(); state = 37; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 115:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'l' || ch >= 'n' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'm') {AddCh(); state = 117; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 116:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'b' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'a') {AddCh(); state = 118; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 117:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == 'a' || ch >= 'c' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'b') {AddCh(); state = 119; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 118:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'k' || ch >= 'm' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'l') {AddCh(); state = 120; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 119:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'd' || ch >= 'f' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'e') {AddCh(); state = 121; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 120:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == '(') {AddCh(); state = 36; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 121:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'q' || ch >= 's' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == 'r') {AddCh(); state = 122; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 122:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else if (ch == '(') {AddCh(); state = 38; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-
-				default:
-			}
-		}
-		t.val = new String(tval, 0, tlen);
-		return t;
-	}
-	
-	private void SetScannerBehindT() {
-		buffer.setPos(t.pos);
-		NextCh();
-		line = t.line; col = t.col; charPos = t.charPos;
-		for (int i = 0; i < tlen; i++) NextCh();
-	}
-	
-	// get the next token (possibly a token already seen during peeking)
-	public Token Scan () {
-		if (tokens.next == null) {
-			return NextToken();
-		} else {
-			pt = tokens = tokens.next;
-			return tokens;
-		}
-	}
-
-	// get the next token, ignore pragmas
-	public Token Peek () {
-		do {
-			if (pt.next == null) {
-				pt.next = NextToken();
-			}
-			pt = pt.next;
-		} while (pt.kind > maxT); // skip pragmas
-
-		return pt;
-	}
-
-	// make sure that peeking starts at current scan position
-	public void ResetPeek () { pt = tokens; }
-
-} // end Scanner
diff --git a/src/qir/parser/qir.atg b/src/qir/parser/qir.atg
deleted file mode 100644
index 66c6a4d0b001d5a90dba0d6b5dd475c949f574ac..0000000000000000000000000000000000000000
--- a/src/qir/parser/qir.atg
+++ /dev/null
@@ -1,334 +0,0 @@
-COMPILER QIR
-
-CHARACTERS
-
-letter = 'A'..'Z' + 'a'..'z'.
-nonZeroDigit = "123456789".
-digit = "0123456789".
-cr = '\r'.
-lf = '\n'.
-tab = '\t'.
-stringChar = ANY - "\"" - '\\' - cr - lf.
-
-TOKENS
-
-identifier = letter {letter | digit | '_'}.
-stringLiteral = "\"" { stringChar } "\"".
-numberLiteral = "0" | nonZeroDigit { digit } | "-" nonZeroDigit { digit }.
-doubleLiteral = digit { digit } "." digit { digit } | "-" digit { digit } "." digit { digit }.
-
-PRAGMAS
-
-COMMENTS FROM "/*" TO "*/"
-COMMENTS FROM "//" TO lf
-IGNORE cr + lf + tab
-
-PRODUCTIONS
-
-QIR<out QIRNode res> = Or<out QIRNode expr>									(. res = expr; .)
-.
-
-Or<out QIRNode res> =
-And<out res>																(. final Token srcToken = t; .)
-{ "||" And<out QIRNode right>												(. res = QIROrNodeGen.create(srcFromToken(srcToken), res, right); .)
-}
-.
-
-And<out QIRNode res> =
-Equal<out res>																(. final Token srcToken = t; .)
-{ "&&" Equal<out QIRNode right>												(. res = QIRAndNodeGen.create(srcFromToken(srcToken), res, right); .)
-}
-.
-
-Equal<out QIRNode res> =
-Lower<out res>																(. final Token srcToken = t; .)
-{ "==" Lower<out QIRNode right>												(. res = QIREqualNodeGen.create(srcFromToken(srcToken), res, right); .)
-}
-.
-
-Lower<out QIRNode res> =
-Plus<out res>																(. final Token srcToken = t; .)
-{ ("<" | "<=")																(. final Token opToken = t; .)
-Plus<out QIRNode right>														(. switch (opToken.val) {
-																				   case "<":
-																					   res = QIRLowerThanNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																				   default:
-																					   res = QIRLowerOrEqualNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																			   } .)
-}
-.
-
-Plus<out QIRNode res> =
-Star<out res>																(. final Token srcToken = t; .)
-{ ("+" | "-")																(. final Token opToken = t; .)
-Star<out QIRNode right>														(. switch (opToken.val) {
-																				   case "+":
-																					   res = QIRPlusNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																				   default:
-																					   res = QIRMinusNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																			   } .)
-}
-.
-
-Star<out QIRNode res> =
-Not<out res>																(. final Token srcToken = t; .)
-{ ("*" | "/" | "%")															(. final Token opToken = t; .)
-Not<out QIRNode right>														(. switch (opToken.val) {
-																				   case "*":
-																					   res = QIRStarNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																				   case "/":
-																					   res = QIRDivNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																				   default:
-																					   res = QIRModNodeGen.create(srcFromToken(srcToken), res, right);
-																					   break;
-																			   } .)
-}
-.
-
-Not<out QIRNode res> =														(. final Token srcToken = t;
-																			   int nots = 0; .)
-{ "!"																		(. nots++; .)
-} Application<out res>														(. while (nots-- > 0)
-																				   res = QIRNotNodeGen.create(srcFromToken(srcToken), res); .)
-.
-
-Application<out QIRNode res> =
-Tupledestr<out res>															(. final Token srcToken = t; .)
-{ "@" Tupledestr<out QIRNode right>											(. res = new QIRApply(srcFromToken(srcToken), res, right); .)
-}
-.
-
-Tupledestr<out QIRNode res> =
-Expression<out res>															(. final Token srcToken = t; .)
-{ "." identifier															(. res = new QIRRdestr(srcFromToken(srcToken), res, t.val); .)
-}
-.
-
-Expression<out QIRNode res> = 												(. res = null; .)
-(
-Variable<out QIRVariable result>											(. res = result; .)
-| Lambda<out QIRLambda result>												(. res = result; .)
-| Ifexpr<out QIRIf result>													(. res = result; .)
-| Tuplecons<out QIRRecord result>											(. res = result; .)
-| Listcons<out QIRList result>												(. res = result; .)
-| Listdestr<out QIRLdestr result>											(. res = result; .)
-| External<out QIRExternal result>											(. res = result; .)
-| Table<out QIRTable result>												(. res = result; .)
-| Bignumber<out QIRBigNumber result>										(. res = result; .)
-| Boolean<out QIRBoolean result>											(. res = result; .)
-| Number<out QIRNumber result>												(. res = result; .)
-| Double<out QIRDouble result>												(. res = result; .)
-| Null<out QIRNull result>													(. res = result; .)
-| String<out QIRString result>												(. res = result; .)
-| '%'																		(. final Token srcToken = t;
-																			   final List<QIRNode> args = new ArrayList<>(); .)
-identifier																	(. final Token opName = t; .)
-'('
-[
-QIR<out QIRNode arg>														(. args.add(arg); .)
-{
-',' QIR<out arg>															(. args.add(arg); .)
-} ]																			(. res = new ExternalOperator(srcFromToken(srcToken), opName.val, args); .)
-| Project<out QIRProject result>											(. res = result; .)
-| Scan<out QIRScan result>													(. res = result; .)
-| Filter<out QIRFilter result>												(. res = result; .)
-| Groupby<out QIRGroupBy result>											(. res = result; .)
-| Sortby<out QIRSortBy result>												(. res = result; .)
-| Join<out QIRJoin result>													(. res = result; .)
-| Leftjoin<out QIRLeftJoin result>											(. res = result; .)
-| Rightjoin<out QIRRightJoin result>										(. res = result; .)
-| '(' QIR<out res> ')'
-).
-
-Variable<out QIRVariable res> =
-identifier																	(. res = new QIRVariable(srcFromToken(t), t.val); .)
-.
-
-Lambda<out QIRLambda res> =
-"fun"																		(. final Token srcToken = t;
-																			   Token funName = null;
-																			   QIRType type = null; .)
-[ "#" identifier															(. funName = t; .)
-] [ ":" Type<out type> ] Variable<out QIRVariable var> "->"
-QIR<out QIRNode body>														(. res = new QIRLambda(srcFromToken(srcToken), funName == null ? null : funName.val, var, body, new FrameDescriptor());
-																			   if (type != null)
-																				 res.setType(type, QIRDefaultTypeSystemVisitor.class);
-																			.)
-.
-
-Ifexpr<out QIRIf res> =
-"if"																		(. final Token srcToken = t; .)
-QIR<out QIRNode cond> "then" QIR<out QIRNode thenNode> "else"
-QIR<out QIRNode elseNode>													(. res = new QIRIf(srcFromToken(srcToken), cond, thenNode, elseNode); .)
-.
-
-Tuplecons<out QIRRecord res> =
-"{"																			(. res = QIRRnil.getInstance();
-																			   final Token srcToken = t;
-																			   Token idToken;
-																			   QIRType type = null; .)
-[
-identifier																	(. idToken = t; .)
-"=" QIR<out QIRNode value>													(. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .)
-{
-";" identifier																(. idToken = t; .)
-"=" QIR<out value>															(. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .)
-} ] "}" [ ":" RecordType<out type> ]										(. if (type != null)
-																				 res.setType(type, QIRDefaultTypeSystemVisitor.class); .)
-.
-
-Type<out QIRType res> =														(. res = null; .)
-(
-NonFunctionType<out QIRType first>											(. final List<QIRType> types = new ArrayList<>();
-																			   types.add(first); .)
-{ "->" NonFunctionType<out QIRType type>									(. types.add(type); .)
-}																			(. res = types.size() == 1 ? first : new QIRFunctionType(types.subList(0, types.size() - 1).toArray(new QIRType[types.size() - 1]), types.get(types.size() - 1)); .)
-)
-.
-
-NonFunctionType<out QIRType res> =											(. res = null; .)
-(
-ConstantType<out res>
-| RecordType<out res>
-| ListType<out res>
-| "(" Type<out res> ")"
-)
-.
-
-ConstantType<out QIRType res> =												(. res = null; .)
-(
-"any"																		(. res = QIRAnyType.getInstance(); .)
-| "int"																		(. res = QIRNumberType.getInstance(); .)
-| "big_int"																	(. res = QIRBigNumberType.getInstance(); .)
-| "double"																	(. res = QIRDoubleType.getInstance(); .)
-| "bool"																	(. res = QIRBooleanType.getInstance(); .)
-| "string"																	(. res = QIRStringType.getInstance(); .)
-)
-.
-
-RecordType<out QIRRecordType res> =
-"{"																			(. final Map<String, QIRType> types = new HashMap<>(); .)
-[
-identifier																	(. Token idToken = t; .)
-":" Type<out QIRType type>													(. types.put(idToken.val, type); .)
-{ ";" identifier															(. idToken = t; .)
-":" Type<out type>															(. types.put(idToken.val, type); .)
-} ]
-"}"																			(. res = new QIRRecordType(types); .)
-.
-
-ListType<out QIRListType res> =
-"list" "[" Type<out QIRType type> "]"										(. res = new QIRListType(type); .)
-.
-
-Listcons<out QIRList res> =
-"["																			(. res = QIRLnil.getInstance();
-																			   QIRType type = null;
-																			   final Token srcToken = t; .)
-[
-QIR<out QIRNode value>														(. res = new QIRLcons(srcFromToken(srcToken), value, res); .)
-{
-";" QIR<out value>															(. res = new QIRLcons(srcFromToken(srcToken), value, res); .)
-} ] "]" [ ":" ListType<out type> ]											(. if (type != null)
-																				 res.setType(type, QIRDefaultTypeSystemVisitor.class); .)
-.
-
-Listdestr<out QIRLdestr res> =
-"match"																		(. final Token srcToken = t; .)
-QIR<out QIRNode list> "with" "empty" "->" QIR<out QIRNode ifEmpty>
-"else" "->" QIR<out QIRNode handler> ')'									(. res = new QIRLdestr(srcFromToken(srcToken), list, ifEmpty, handler); .)
-.
-
-External<out QIRExternal res> =
-"External("																	(. final Token srcToken = t; .)
-identifier																	(. final Token eName = t; .)
-')'																			(. res = new QIRExternal(srcFromToken(srcToken), eName.val); .)
-.
-
-Table<out QIRTable res> =
-"Table("																	(. final Token srcToken = t; .)
-QIR<out QIRNode tableName> "," QIR<out QIRNode dbName> ","
-QIR<out QIRNode configFile> "," QIR<out QIRNode schemaName>
-')'																			(. res = new QIRTable(srcFromToken(srcToken), tableName, dbName, configFile, schemaName); .)
-.
-
-Bignumber<out QIRBigNumber res> =
-"BigNumber("																(. final Token srcToken = t; .)
-numberLiteral																(. final Token number = t; .)
-')'																			(. res = new QIRBigNumber(srcFromToken(srcToken), new BigInteger(number.val)); .)
-.
-
-Boolean<out QIRBoolean res> =												(. res = null; .)
-(
-"true"																		(. res = QIRBoolean.TRUE; .)
-| "false"																	(. res = QIRBoolean.FALSE; .)
-)
-.
-
-Number<out QIRNumber res> =
-numberLiteral																(. res = new QIRNumber(srcFromToken(t), Long.parseLong(t.val)); .)
-.
-
-Double<out QIRDouble res> =
-doubleLiteral																(. res = new QIRDouble(srcFromToken(t), Double.parseDouble(t.val)); .)
-.
-
-Null<out QIRNull res> =
-"NULL"																		(. res = QIRNull.getInstance(); .)
-.
-
-String<out QIRString res> =
-stringLiteral																(. res = new QIRString(srcFromToken(t), t.val); .)
-.
-
-Project<out QIRProject res> =
-"%Project("																	(. final Token srcToken = t; .)
-QIR<out QIRNode formatter> "," QIR<out QIRNode child> ')'					(. res = new QIRProject(srcFromToken(srcToken), formatter, child); .)
-.
-
-Scan<out QIRScan res> =
-"%Scan("																	(. final Token srcToken = t; .)
-QIR<out QIRNode child> ')'													(. res = new QIRScan(srcFromToken(srcToken), child); .)
-.
-
-Filter<out QIRFilter res> =
-"%Filter("																	(. final Token srcToken = t; .)
-QIR<out QIRNode filter> "," QIR<out QIRNode child> ')'						(. res = new QIRFilter(srcFromToken(srcToken), filter, child); .)
-.
-
-Groupby<out QIRGroupBy res> =
-"%GroupBy("																	(. final Token srcToken = t; .)
-QIR<out QIRNode group> "," QIR<out QIRNode child> ')'						(. res = new QIRGroupBy(srcFromToken(srcToken), group, child); .)
-.
-
-Sortby<out QIRSortBy res> =
-"%SortBy("																	(. final Token srcToken = t; .)
-QIR<out QIRNode sort> "," QIR<out QIRNode isAscending>
-"," QIR<out QIRNode child> ')'												(. res = new QIRSortBy(srcFromToken(srcToken), sort, isAscending, child); .)
-.
-
-Join<out QIRJoin res> =
-"%Join("																	(. final Token srcToken = t; .)
-QIR<out QIRNode filter> "," QIR<out QIRNode left> ","
-QIR<out QIRNode right> ')'													(. res = new QIRJoin(srcFromToken(srcToken), filter, left, right); .)
-.
-
-Leftjoin<out QIRLeftJoin res> =
-"%LeftJoin("																(. final Token srcToken = t; .)
-QIR<out QIRNode filter> "," QIR<out QIRNode left> ","
-QIR<out QIRNode right> ')'													(. res = new QIRLeftJoin(srcFromToken(srcToken), filter, left, right); .)
-.
-
-Rightjoin<out QIRRightJoin res> =
-"%RightJoin("																(. final Token srcToken = t; .)
-QIR<out QIRNode filter> "," QIR<out QIRNode left> ","
-QIR<out QIRNode right> ')'													(. res = new QIRRightJoin(srcFromToken(srcToken), filter, left, right); .)
-.
-
-END QIR.
\ No newline at end of file
diff --git a/src/qir/parser/qir.g4 b/src/qir/parser/qir.g4
new file mode 100644
index 0000000000000000000000000000000000000000..04bfd9cadecf021383d455b9b8e147cfe611903c
--- /dev/null
+++ b/src/qir/parser/qir.g4
@@ -0,0 +1,260 @@
+grammar qir;
+
+@lexer::header
+{
+package qir.parser;
+}
+
+@parser::header
+{
+package qir.parser;
+
+import java.util.Optional;
+import java.math.BigInteger;
+
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.source.SourceSection;
+
+import qir.ast.*;
+import qir.ast.data.*;
+import qir.ast.expression.*;
+import qir.ast.expression.arithmetic.*;
+import qir.ast.expression.logic.*;
+import qir.ast.expression.relational.*;
+import qir.ast.operator.*;
+import qir.util.QIRException;
+}
+
+@parser::members
+{
+	private Source source;
+
+	private static final class BailoutErrorListener extends BaseErrorListener {
+	    private final Source source;
+	    BailoutErrorListener(Source source) {
+	        this.source = source;
+	    }
+	    @Override
+	    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+	        String location = "-- line " + line + " col " + (charPositionInLine + 1) + ": ";
+	        throw new QIRException("Parse error: " + location + msg);
+	    }
+	}
+
+	private final SourceSection srcFromToken(final Token begin, final Token end) {
+        return source.createSection(begin.getStartIndex(), end.getStopIndex() - begin.getStartIndex());
+    }
+
+	public void SemErr(Token token, String message) {
+	    int col = token.getCharPositionInLine() + 1;
+	    String location = "-- line " + token.getLine() + " col " + col + ": ";
+	    throw new QIRException("Parse error: " + location + message);
+	}
+
+    public static QIRNode parseQIR(Source source) {
+        qirLexer lexer = new qirLexer(CharStreams.fromString(source.getCharacters().toString()));
+        qirParser parser = new qirParser(new CommonTokenStream(lexer));
+        lexer.removeErrorListeners();
+        parser.removeErrorListeners();
+        BailoutErrorListener listener = new BailoutErrorListener(source);
+        lexer.addErrorListener(listener);
+        parser.addErrorListener(listener);
+        parser.source = source;
+        return parser.qir().result;
+    }
+}
+
+// parser
+
+qir returns [QIRNode result] :
+or EOF								{ $result = $or.result; }
+;
+
+or returns [QIRNode result] :
+t=and								{ $result = $and.result; }
+(
+	'||' and						{ $result = QIROrNodeGen.create(srcFromToken($t.start, $and.start), $result, $and.result); }
+)*
+;
+
+and returns [QIRNode result] :
+t=equal								{ $result = $equal.result; }
+(
+	'&&' equal						{ $result = QIRAndNodeGen.create(srcFromToken($t.start, $equal.start), $result, $equal.result); }
+)*
+;
+
+equal returns [QIRNode result] :
+t=lower								{ $result = $lower.result; }
+(
+	'==' lower						{ $result = QIREqualNodeGen.create(srcFromToken($t.start, $lower.start), $result, $lower.result); }
+)*
+;
+
+lower returns [QIRNode result] :
+t=plus								{ $result = $plus.result; }
+(
+	'<' plus						{ $result = QIRLowerThanNodeGen.create(srcFromToken($t.start, $plus.start), $result, $plus.result); }
+|	'<=' plus						{ $result = QIRLowerOrEqualNodeGen.create(srcFromToken($t.start, $plus.start), $result, $plus.result); }
+)?
+;
+
+plus returns [QIRNode result] :
+t=star								{ $result = $star.result; }
+(
+	'+' star						{ $result = QIRPlusNodeGen.create(srcFromToken($t.start, $star.start), $result, $star.result); }
+|	'-' star						{ $result = QIRMinusNodeGen.create(srcFromToken($t.start, $star.start), $result, $star.result); }
+)*
+;
+
+star returns [QIRNode result] :
+t=not								{ $result = $not.result; }
+(
+	'*' not							{ $result = QIRStarNodeGen.create(srcFromToken($t.start, $not.start), $result, $not.result); }
+|	'/' not							{ $result = QIRDivNodeGen.create(srcFromToken($t.start, $not.start), $result, $not.result); }
+|	'%' not							{ $result = QIRModNodeGen.create(srcFromToken($t.start, $not.start), $result, $not.result); }
+)*
+;
+
+not returns [QIRNode result] :
+									{ Optional<Token> t = Optional.empty(); }
+(
+	op='!'							{ t = Optional.of($op); }
+)?
+apply								{ $result = t.isPresent() ? QIRNotNodeGen.create(srcFromToken(t.get(), $apply.start), $apply.result) : $apply.result; }
+;
+
+apply returns [QIRNode result] :
+t=tdestr							{ $result = $tdestr.result; }
+(
+	'@' tdestr						{ $result = new QIRApply(srcFromToken($t.start, $tdestr.start), $result, $tdestr.result); }
+)*
+;
+
+tdestr returns [QIRNode result] :
+t=expr								{ $result = $expr.result; }
+(
+	'.' IDENTIFIER					{ $result = new QIRRdestr(srcFromToken($t.start, $IDENTIFIER), $result, $IDENTIFIER.getText()); }
+)*
+;
+
+expr returns [QIRNode result] :
+(
+	IDENTIFIER						{ $result = new QIRVariable(srcFromToken($IDENTIFIER, $IDENTIFIER), $IDENTIFIER.getText()); }
+|	lambda							{ $result = $lambda.result; }
+|	ifexpr							{ $result = $ifexpr.result; }
+|	tcons							{ $result = $tcons.result; }
+|	lcons							{ $result = $lcons.result; }
+|	ldestr							{ $result = $ldestr.result; }
+|	t='External' '(' IDENTIFIER
+	end=')'							{ $result = new QIRExternal(srcFromToken($t, $end), $IDENTIFIER.getText()); }
+|	t='Table' '('
+		tableName=or
+		',' dbName=or
+		',' configFile=or
+		',' schemaName=or
+	end=')'							{ $result = new QIRTable(srcFromToken($t, $end), $tableName.result, $dbName.result, $configFile.result, $schemaName.result); }
+|	t='BigNumber' '(' NUMBER
+	end=')'							{ $result = new QIRBigNumber(srcFromToken($t, $end), new BigInteger($NUMBER.getText())); }
+|	'true'							{ $result = QIRBoolean.TRUE; }
+|	'false'							{ $result = QIRBoolean.FALSE; }
+|	NUMBER							{ $result = new QIRNumber(srcFromToken($NUMBER, $NUMBER), Long.parseLong($NUMBER.getText())); }
+|	DOUBLE							{ $result = new QIRDouble(srcFromToken($DOUBLE, $DOUBLE), Double.parseDouble($DOUBLE.getText())); }
+|	'null'							{ $result = QIRNull.getInstance(); }
+|	STRING							{ $result = new QIRString(srcFromToken($STRING, $STRING), $STRING.getText()); }
+|	dataop							{ $result = $dataop.result; }
+| '(' expr ')'						{ $result = $expr.result; }
+)
+;
+
+lambda returns [QIRNode result] :
+t='fun'								{ String funName = null; }
+(
+	'#' IDENTIFIER					{ funName = $IDENTIFIER.getText(); }
+)?
+var=IDENTIFIER '->' or				{ $result = new QIRLambda(srcFromToken($t, $or.start), funName, new QIRVariable(srcFromToken($var, $var), $var.getText()), $or.result, new FrameDescriptor()); }
+;
+
+ifexpr returns [QIRNode result] :
+t='if' cond=or
+'then' thenNode=or
+'else' elseNode=or					{ $result = new QIRIf(srcFromToken($t, $elseNode.start), $cond.result, $thenNode.result, $elseNode.result); }
+;
+
+tcons returns [QIRNode result] :
+t='{'								{ $result = QIRRnil.getInstance(); }
+(
+IDENTIFIER '=' or					{ $result = new QIRRcons(srcFromToken($t, $or.start), $IDENTIFIER.getText(), $or.result, $result); }
+(
+';' IDENTIFIER '=' or				{ $result = new QIRRcons(srcFromToken($t, $or.start), $IDENTIFIER.getText(), $or.result, $result); }
+)*
+)?
+'}'
+;
+
+lcons returns [QIRNode result] :
+t='['								{ $result = QIRLnil.getInstance(); }
+(
+or									{ $result = new QIRLcons(srcFromToken($t, $or.start), $or.result, $result); }
+(
+';' or								{ $result = new QIRLcons(srcFromToken($t, $or.start), $or.result, $result); }
+)*
+)?
+']'
+;
+
+ldestr returns [QIRNode result] :
+t='match' list=or
+'with' 'empty' '->' ifEmpty=or
+'else' '->' handler=or				{ $result = new QIRLdestr(srcFromToken($t, $handler.start), $list.result, $ifEmpty.result, $handler.result); }
+;
+
+dataop returns [QIRNode result] :
+t='%'
+(
+	'Project' '(' formatter=or
+	',' child=or end=')'			{ $result = new QIRProject(srcFromToken($t, $end), $formatter.result, $child.result); }
+|	'Scan' '(' child=or end=')'		{ $result = new QIRScan(srcFromToken($t, $end), $child.result); }
+|	'Filter' '(' filter=or
+	',' child=or end=')'			{ $result = new QIRFilter(srcFromToken($t, $end), $filter.result, $child.result); }
+|	'GroupBy' '(' group=or
+	',' child=or end=')'			{ $result = new QIRGroupBy(srcFromToken($t, $end), $group.result, $child.result); }
+|	'SortBy' '(' sort=or
+	',' isAscending=or
+	',' child=or end=')'			{ $result = new QIRSortBy(srcFromToken($t, $end), $sort.result, $isAscending.result, $child.result); }
+|	'Join' '(' filter=or
+	',' left=or
+	',' right=or end=')'			{ $result = new QIRJoin(srcFromToken($t, $end), $filter.result, $left.result, $right.result); }
+|	'LeftJoin' '(' filter=or
+	',' left=or
+	',' right=or end=')'			{ $result = new QIRLeftJoin(srcFromToken($t, $end), $filter.result, $left.result, $right.result); }
+|	'RightJoin' '(' filter=or
+	',' left=or
+	',' right=or end=')'			{ $result = new QIRRightJoin(srcFromToken($t, $end), $filter.result, $left.result, $right.result); }
+|	IDENTIFIER '('					{ final List<QIRNode> args = new ArrayList<>(); }
+	(
+		arg=or						{ args.add($arg.result); }
+		(
+			',' arg=or				{ args.add($arg.result); }
+		)*
+	)?
+	end=')'							{ $result = new ExternalOperator(srcFromToken($t, $end), $IDENTIFIER.getText(), args); }
+)
+;
+
+// lexer
+
+WS : [ \t\r\n\u000C]+ -> skip;
+COMMENT : '/*' .*? '*/' -> skip;
+LINE_COMMENT : '//' ~[\r\n]* -> skip;
+
+fragment LETTER : [A-Z] | [a-z] | '_' | '$';
+fragment NON_ZERO_DIGIT : [1-9];
+fragment DIGIT : [0-9];
+fragment STRING_CHAR : ~('"' | '\\' | '\r' | '\n');
+
+IDENTIFIER : LETTER (LETTER | DIGIT)*;
+STRING : '"' STRING_CHAR* '"';
+NUMBER : '0' | NON_ZERO_DIGIT DIGIT*;
+DOUBLE : '-'? DIGIT DIGIT* '.' DIGIT DIGIT*;
\ No newline at end of file
diff --git a/src/qir/parser/qirBaseListener.java b/src/qir/parser/qirBaseListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..30360154eeab59df014a73b7f1be7c6be8d85ed5
--- /dev/null
+++ b/src/qir/parser/qirBaseListener.java
@@ -0,0 +1,431 @@
+// Generated from qir.g4 by ANTLR 4.7
+
+package qir.parser;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ErrorNode;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+/**
+ * This class provides an empty implementation of {@link qirListener}, which can be extended to
+ * create a listener which only needs to handle a subset of the available methods.
+ */
+public class qirBaseListener implements qirListener {
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterQir(qirParser.QirContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitQir(qirParser.QirContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterOr(qirParser.OrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitOr(qirParser.OrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterAnd(qirParser.AndContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitAnd(qirParser.AndContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterEqual(qirParser.EqualContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitEqual(qirParser.EqualContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterLower(qirParser.LowerContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitLower(qirParser.LowerContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterPlus(qirParser.PlusContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitPlus(qirParser.PlusContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterStar(qirParser.StarContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitStar(qirParser.StarContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterNot(qirParser.NotContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitNot(qirParser.NotContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterApply(qirParser.ApplyContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitApply(qirParser.ApplyContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterTdestr(qirParser.TdestrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitTdestr(qirParser.TdestrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterExpr(qirParser.ExprContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitExpr(qirParser.ExprContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterLambda(qirParser.LambdaContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitLambda(qirParser.LambdaContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterIfexpr(qirParser.IfexprContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitIfexpr(qirParser.IfexprContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterTcons(qirParser.TconsContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitTcons(qirParser.TconsContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterLcons(qirParser.LconsContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitLcons(qirParser.LconsContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterLdestr(qirParser.LdestrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitLdestr(qirParser.LdestrContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterDataop(qirParser.DataopContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitDataop(qirParser.DataopContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void enterEveryRule(ParserRuleContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void exitEveryRule(ParserRuleContext ctx) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void visitTerminal(TerminalNode node) {
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * The default implementation does nothing.
+     * </p>
+     */
+    @Override
+    public void visitErrorNode(ErrorNode node) {
+    }
+}
\ No newline at end of file
diff --git a/src/qir/parser/qirLexer.java b/src/qir/parser/qirLexer.java
new file mode 100644
index 0000000000000000000000000000000000000000..dffae4c628a14dd63d1f166d2122c866df6e1647
--- /dev/null
+++ b/src/qir/parser/qirLexer.java
@@ -0,0 +1,256 @@
+// Generated from qir.g4 by ANTLR 4.7
+
+package qir.parser;
+
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class qirLexer extends Lexer {
+	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
+	public static final int
+		T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, 
+		T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, 
+		T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, 
+		T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, 
+		T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, 
+		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, 
+		WS=46, COMMENT=47, LINE_COMMENT=48, IDENTIFIER=49, STRING=50, NUMBER=51, 
+		DOUBLE=52;
+	public static String[] channelNames = {
+		"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
+	};
+
+	public static String[] modeNames = {
+		"DEFAULT_MODE"
+	};
+
+	public static final String[] ruleNames = {
+		"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", 
+		"T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", 
+		"T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", 
+		"T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", 
+		"T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", 
+		"T__41", "T__42", "T__43", "T__44", "WS", "COMMENT", "LINE_COMMENT", "LETTER", 
+		"NON_ZERO_DIGIT", "DIGIT", "STRING_CHAR", "IDENTIFIER", "STRING", "NUMBER", 
+		"DOUBLE"
+	};
+
+	private static final String[] _LITERAL_NAMES = {
+		null, "'||'", "'&&'", "'=='", "'<'", "'<='", "'+'", "'-'", "'*'", "'/'", 
+		"'%'", "'!'", "'@'", "'.'", "'External'", "'('", "')'", "'Table'", "','", 
+		"'BigNumber'", "'true'", "'false'", "'null'", "'fun'", "'#'", "'->'", 
+		"'if'", "'then'", "'else'", "'{'", "'='", "';'", "'}'", "'['", "']'", 
+		"'match'", "'with'", "'empty'", "'Project'", "'Scan'", "'Filter'", "'GroupBy'", 
+		"'SortBy'", "'Join'", "'LeftJoin'", "'RightJoin'"
+	};
+	private static final String[] _SYMBOLIC_NAMES = {
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, "WS", "COMMENT", 
+		"LINE_COMMENT", "IDENTIFIER", "STRING", "NUMBER", "DOUBLE"
+	};
+	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+	/**
+	 * @deprecated Use {@link #VOCABULARY} instead.
+	 */
+	@Deprecated
+	public static final String[] tokenNames;
+	static {
+		tokenNames = new String[_SYMBOLIC_NAMES.length];
+		for (int i = 0; i < tokenNames.length; i++) {
+			tokenNames[i] = VOCABULARY.getLiteralName(i);
+			if (tokenNames[i] == null) {
+				tokenNames[i] = VOCABULARY.getSymbolicName(i);
+			}
+
+			if (tokenNames[i] == null) {
+				tokenNames[i] = "<INVALID>";
+			}
+		}
+	}
+
+	@Override
+	@Deprecated
+	public String[] getTokenNames() {
+		return tokenNames;
+	}
+
+	@Override
+
+	public Vocabulary getVocabulary() {
+		return VOCABULARY;
+	}
+
+
+	public qirLexer(CharStream input) {
+		super(input);
+		_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+	}
+
+	@Override
+	public String getGrammarFileName() { return "qir.g4"; }
+
+	@Override
+	public String[] getRuleNames() { return ruleNames; }
+
+	@Override
+	public String getSerializedATN() { return _serializedATN; }
+
+	@Override
+	public String[] getChannelNames() { return channelNames; }
+
+	@Override
+	public String[] getModeNames() { return modeNames; }
+
+	@Override
+	public ATN getATN() { return _ATN; }
+
+	public static final String _serializedATN =
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\66\u0184\b\1\4\2"+
+		"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
+		"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
+		"\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+
+		"\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+
+		" \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+
+		"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
+		"\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\3\2\3\2\3\2\3\3\3\3\3"+
+		"\3\3\4\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13"+
+		"\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+
+		"\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\24"+
+		"\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25"+
+		"\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30"+
+		"\3\30\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34"+
+		"\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3"+
+		"#\3$\3$\3$\3$\3$\3$\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3"+
+		"\'\3\'\3\'\3\'\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3"+
+		"*\3*\3+\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3"+
+		".\3.\3.\3.\3.\3.\3.\3.\3.\3.\3/\6/\u0130\n/\r/\16/\u0131\3/\3/\3\60\3"+
+		"\60\3\60\3\60\7\60\u013a\n\60\f\60\16\60\u013d\13\60\3\60\3\60\3\60\3"+
+		"\60\3\60\3\61\3\61\3\61\3\61\7\61\u0148\n\61\f\61\16\61\u014b\13\61\3"+
+		"\61\3\61\3\62\5\62\u0150\n\62\3\63\3\63\3\64\3\64\3\65\3\65\3\66\3\66"+
+		"\3\66\7\66\u015b\n\66\f\66\16\66\u015e\13\66\3\67\3\67\7\67\u0162\n\67"+
+		"\f\67\16\67\u0165\13\67\3\67\3\67\38\38\38\78\u016c\n8\f8\168\u016f\13"+
+		"8\58\u0171\n8\39\59\u0174\n9\39\39\79\u0178\n9\f9\169\u017b\139\39\39"+
+		"\39\79\u0180\n9\f9\169\u0183\139\3\u013b\2:\3\3\5\4\7\5\t\6\13\7\r\b\17"+
+		"\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+"+
+		"\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+"+
+		"U,W-Y.[/]\60_\61a\62c\2e\2g\2i\2k\63m\64o\65q\66\3\2\b\5\2\13\f\16\17"+
+		"\"\"\4\2\f\f\17\17\6\2&&C\\aac|\3\2\63;\3\2\62;\6\2\f\f\17\17$$^^\2\u018a"+
+		"\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+
+		"\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+
+		"\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+
+		"\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+
+		"\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+
+		"\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+
+		"\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+
+		"U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+
+		"\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\3s\3\2\2\2\5v\3\2\2"+
+		"\2\7y\3\2\2\2\t|\3\2\2\2\13~\3\2\2\2\r\u0081\3\2\2\2\17\u0083\3\2\2\2"+
+		"\21\u0085\3\2\2\2\23\u0087\3\2\2\2\25\u0089\3\2\2\2\27\u008b\3\2\2\2\31"+
+		"\u008d\3\2\2\2\33\u008f\3\2\2\2\35\u0091\3\2\2\2\37\u009a\3\2\2\2!\u009c"+
+		"\3\2\2\2#\u009e\3\2\2\2%\u00a4\3\2\2\2\'\u00a6\3\2\2\2)\u00b0\3\2\2\2"+
+		"+\u00b5\3\2\2\2-\u00bb\3\2\2\2/\u00c0\3\2\2\2\61\u00c4\3\2\2\2\63\u00c6"+
+		"\3\2\2\2\65\u00c9\3\2\2\2\67\u00cc\3\2\2\29\u00d1\3\2\2\2;\u00d6\3\2\2"+
+		"\2=\u00d8\3\2\2\2?\u00da\3\2\2\2A\u00dc\3\2\2\2C\u00de\3\2\2\2E\u00e0"+
+		"\3\2\2\2G\u00e2\3\2\2\2I\u00e8\3\2\2\2K\u00ed\3\2\2\2M\u00f3\3\2\2\2O"+
+		"\u00fb\3\2\2\2Q\u0100\3\2\2\2S\u0107\3\2\2\2U\u010f\3\2\2\2W\u0116\3\2"+
+		"\2\2Y\u011b\3\2\2\2[\u0124\3\2\2\2]\u012f\3\2\2\2_\u0135\3\2\2\2a\u0143"+
+		"\3\2\2\2c\u014f\3\2\2\2e\u0151\3\2\2\2g\u0153\3\2\2\2i\u0155\3\2\2\2k"+
+		"\u0157\3\2\2\2m\u015f\3\2\2\2o\u0170\3\2\2\2q\u0173\3\2\2\2st\7~\2\2t"+
+		"u\7~\2\2u\4\3\2\2\2vw\7(\2\2wx\7(\2\2x\6\3\2\2\2yz\7?\2\2z{\7?\2\2{\b"+
+		"\3\2\2\2|}\7>\2\2}\n\3\2\2\2~\177\7>\2\2\177\u0080\7?\2\2\u0080\f\3\2"+
+		"\2\2\u0081\u0082\7-\2\2\u0082\16\3\2\2\2\u0083\u0084\7/\2\2\u0084\20\3"+
+		"\2\2\2\u0085\u0086\7,\2\2\u0086\22\3\2\2\2\u0087\u0088\7\61\2\2\u0088"+
+		"\24\3\2\2\2\u0089\u008a\7\'\2\2\u008a\26\3\2\2\2\u008b\u008c\7#\2\2\u008c"+
+		"\30\3\2\2\2\u008d\u008e\7B\2\2\u008e\32\3\2\2\2\u008f\u0090\7\60\2\2\u0090"+
+		"\34\3\2\2\2\u0091\u0092\7G\2\2\u0092\u0093\7z\2\2\u0093\u0094\7v\2\2\u0094"+
+		"\u0095\7g\2\2\u0095\u0096\7t\2\2\u0096\u0097\7p\2\2\u0097\u0098\7c\2\2"+
+		"\u0098\u0099\7n\2\2\u0099\36\3\2\2\2\u009a\u009b\7*\2\2\u009b \3\2\2\2"+
+		"\u009c\u009d\7+\2\2\u009d\"\3\2\2\2\u009e\u009f\7V\2\2\u009f\u00a0\7c"+
+		"\2\2\u00a0\u00a1\7d\2\2\u00a1\u00a2\7n\2\2\u00a2\u00a3\7g\2\2\u00a3$\3"+
+		"\2\2\2\u00a4\u00a5\7.\2\2\u00a5&\3\2\2\2\u00a6\u00a7\7D\2\2\u00a7\u00a8"+
+		"\7k\2\2\u00a8\u00a9\7i\2\2\u00a9\u00aa\7P\2\2\u00aa\u00ab\7w\2\2\u00ab"+
+		"\u00ac\7o\2\2\u00ac\u00ad\7d\2\2\u00ad\u00ae\7g\2\2\u00ae\u00af\7t\2\2"+
+		"\u00af(\3\2\2\2\u00b0\u00b1\7v\2\2\u00b1\u00b2\7t\2\2\u00b2\u00b3\7w\2"+
+		"\2\u00b3\u00b4\7g\2\2\u00b4*\3\2\2\2\u00b5\u00b6\7h\2\2\u00b6\u00b7\7"+
+		"c\2\2\u00b7\u00b8\7n\2\2\u00b8\u00b9\7u\2\2\u00b9\u00ba\7g\2\2\u00ba,"+
+		"\3\2\2\2\u00bb\u00bc\7p\2\2\u00bc\u00bd\7w\2\2\u00bd\u00be\7n\2\2\u00be"+
+		"\u00bf\7n\2\2\u00bf.\3\2\2\2\u00c0\u00c1\7h\2\2\u00c1\u00c2\7w\2\2\u00c2"+
+		"\u00c3\7p\2\2\u00c3\60\3\2\2\2\u00c4\u00c5\7%\2\2\u00c5\62\3\2\2\2\u00c6"+
+		"\u00c7\7/\2\2\u00c7\u00c8\7@\2\2\u00c8\64\3\2\2\2\u00c9\u00ca\7k\2\2\u00ca"+
+		"\u00cb\7h\2\2\u00cb\66\3\2\2\2\u00cc\u00cd\7v\2\2\u00cd\u00ce\7j\2\2\u00ce"+
+		"\u00cf\7g\2\2\u00cf\u00d0\7p\2\2\u00d08\3\2\2\2\u00d1\u00d2\7g\2\2\u00d2"+
+		"\u00d3\7n\2\2\u00d3\u00d4\7u\2\2\u00d4\u00d5\7g\2\2\u00d5:\3\2\2\2\u00d6"+
+		"\u00d7\7}\2\2\u00d7<\3\2\2\2\u00d8\u00d9\7?\2\2\u00d9>\3\2\2\2\u00da\u00db"+
+		"\7=\2\2\u00db@\3\2\2\2\u00dc\u00dd\7\177\2\2\u00ddB\3\2\2\2\u00de\u00df"+
+		"\7]\2\2\u00dfD\3\2\2\2\u00e0\u00e1\7_\2\2\u00e1F\3\2\2\2\u00e2\u00e3\7"+
+		"o\2\2\u00e3\u00e4\7c\2\2\u00e4\u00e5\7v\2\2\u00e5\u00e6\7e\2\2\u00e6\u00e7"+
+		"\7j\2\2\u00e7H\3\2\2\2\u00e8\u00e9\7y\2\2\u00e9\u00ea\7k\2\2\u00ea\u00eb"+
+		"\7v\2\2\u00eb\u00ec\7j\2\2\u00ecJ\3\2\2\2\u00ed\u00ee\7g\2\2\u00ee\u00ef"+
+		"\7o\2\2\u00ef\u00f0\7r\2\2\u00f0\u00f1\7v\2\2\u00f1\u00f2\7{\2\2\u00f2"+
+		"L\3\2\2\2\u00f3\u00f4\7R\2\2\u00f4\u00f5\7t\2\2\u00f5\u00f6\7q\2\2\u00f6"+
+		"\u00f7\7l\2\2\u00f7\u00f8\7g\2\2\u00f8\u00f9\7e\2\2\u00f9\u00fa\7v\2\2"+
+		"\u00faN\3\2\2\2\u00fb\u00fc\7U\2\2\u00fc\u00fd\7e\2\2\u00fd\u00fe\7c\2"+
+		"\2\u00fe\u00ff\7p\2\2\u00ffP\3\2\2\2\u0100\u0101\7H\2\2\u0101\u0102\7"+
+		"k\2\2\u0102\u0103\7n\2\2\u0103\u0104\7v\2\2\u0104\u0105\7g\2\2\u0105\u0106"+
+		"\7t\2\2\u0106R\3\2\2\2\u0107\u0108\7I\2\2\u0108\u0109\7t\2\2\u0109\u010a"+
+		"\7q\2\2\u010a\u010b\7w\2\2\u010b\u010c\7r\2\2\u010c\u010d\7D\2\2\u010d"+
+		"\u010e\7{\2\2\u010eT\3\2\2\2\u010f\u0110\7U\2\2\u0110\u0111\7q\2\2\u0111"+
+		"\u0112\7t\2\2\u0112\u0113\7v\2\2\u0113\u0114\7D\2\2\u0114\u0115\7{\2\2"+
+		"\u0115V\3\2\2\2\u0116\u0117\7L\2\2\u0117\u0118\7q\2\2\u0118\u0119\7k\2"+
+		"\2\u0119\u011a\7p\2\2\u011aX\3\2\2\2\u011b\u011c\7N\2\2\u011c\u011d\7"+
+		"g\2\2\u011d\u011e\7h\2\2\u011e\u011f\7v\2\2\u011f\u0120\7L\2\2\u0120\u0121"+
+		"\7q\2\2\u0121\u0122\7k\2\2\u0122\u0123\7p\2\2\u0123Z\3\2\2\2\u0124\u0125"+
+		"\7T\2\2\u0125\u0126\7k\2\2\u0126\u0127\7i\2\2\u0127\u0128\7j\2\2\u0128"+
+		"\u0129\7v\2\2\u0129\u012a\7L\2\2\u012a\u012b\7q\2\2\u012b\u012c\7k\2\2"+
+		"\u012c\u012d\7p\2\2\u012d\\\3\2\2\2\u012e\u0130\t\2\2\2\u012f\u012e\3"+
+		"\2\2\2\u0130\u0131\3\2\2\2\u0131\u012f\3\2\2\2\u0131\u0132\3\2\2\2\u0132"+
+		"\u0133\3\2\2\2\u0133\u0134\b/\2\2\u0134^\3\2\2\2\u0135\u0136\7\61\2\2"+
+		"\u0136\u0137\7,\2\2\u0137\u013b\3\2\2\2\u0138\u013a\13\2\2\2\u0139\u0138"+
+		"\3\2\2\2\u013a\u013d\3\2\2\2\u013b\u013c\3\2\2\2\u013b\u0139\3\2\2\2\u013c"+
+		"\u013e\3\2\2\2\u013d\u013b\3\2\2\2\u013e\u013f\7,\2\2\u013f\u0140\7\61"+
+		"\2\2\u0140\u0141\3\2\2\2\u0141\u0142\b\60\2\2\u0142`\3\2\2\2\u0143\u0144"+
+		"\7\61\2\2\u0144\u0145\7\61\2\2\u0145\u0149\3\2\2\2\u0146\u0148\n\3\2\2"+
+		"\u0147\u0146\3\2\2\2\u0148\u014b\3\2\2\2\u0149\u0147\3\2\2\2\u0149\u014a"+
+		"\3\2\2\2\u014a\u014c\3\2\2\2\u014b\u0149\3\2\2\2\u014c\u014d\b\61\2\2"+
+		"\u014db\3\2\2\2\u014e\u0150\t\4\2\2\u014f\u014e\3\2\2\2\u0150d\3\2\2\2"+
+		"\u0151\u0152\t\5\2\2\u0152f\3\2\2\2\u0153\u0154\t\6\2\2\u0154h\3\2\2\2"+
+		"\u0155\u0156\n\7\2\2\u0156j\3\2\2\2\u0157\u015c\5c\62\2\u0158\u015b\5"+
+		"c\62\2\u0159\u015b\5g\64\2\u015a\u0158\3\2\2\2\u015a\u0159\3\2\2\2\u015b"+
+		"\u015e\3\2\2\2\u015c\u015a\3\2\2\2\u015c\u015d\3\2\2\2\u015dl\3\2\2\2"+
+		"\u015e\u015c\3\2\2\2\u015f\u0163\7$\2\2\u0160\u0162\5i\65\2\u0161\u0160"+
+		"\3\2\2\2\u0162\u0165\3\2\2\2\u0163\u0161\3\2\2\2\u0163\u0164\3\2\2\2\u0164"+
+		"\u0166\3\2\2\2\u0165\u0163\3\2\2\2\u0166\u0167\7$\2\2\u0167n\3\2\2\2\u0168"+
+		"\u0171\7\62\2\2\u0169\u016d\5e\63\2\u016a\u016c\5g\64\2\u016b\u016a\3"+
+		"\2\2\2\u016c\u016f\3\2\2\2\u016d\u016b\3\2\2\2\u016d\u016e\3\2\2\2\u016e"+
+		"\u0171\3\2\2\2\u016f\u016d\3\2\2\2\u0170\u0168\3\2\2\2\u0170\u0169\3\2"+
+		"\2\2\u0171p\3\2\2\2\u0172\u0174\7/\2\2\u0173\u0172\3\2\2\2\u0173\u0174"+
+		"\3\2\2\2\u0174\u0175\3\2\2\2\u0175\u0179\5g\64\2\u0176\u0178\5g\64\2\u0177"+
+		"\u0176\3\2\2\2\u0178\u017b\3\2\2\2\u0179\u0177\3\2\2\2\u0179\u017a\3\2"+
+		"\2\2\u017a\u017c\3\2\2\2\u017b\u0179\3\2\2\2\u017c\u017d\7\60\2\2\u017d"+
+		"\u0181\5g\64\2\u017e\u0180\5g\64\2\u017f\u017e\3\2\2\2\u0180\u0183\3\2"+
+		"\2\2\u0181\u017f\3\2\2\2\u0181\u0182\3\2\2\2\u0182r\3\2\2\2\u0183\u0181"+
+		"\3\2\2\2\17\2\u0131\u013b\u0149\u014f\u015a\u015c\u0163\u016d\u0170\u0173"+
+		"\u0179\u0181\3\b\2\2";
+	public static final ATN _ATN =
+		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/qir/parser/qirListener.java b/src/qir/parser/qirListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d5e50b0b14654e1b4efb8485b2d9c52ad604972
--- /dev/null
+++ b/src/qir/parser/qirListener.java
@@ -0,0 +1,248 @@
+// Generated from qir.g4 by ANTLR 4.7
+
+package qir.parser;
+
+import org.antlr.v4.runtime.tree.ParseTreeListener;
+
+/**
+ * This interface defines a complete listener for a parse tree produced by {@link qirParser}.
+ */
+public interface qirListener extends ParseTreeListener {
+    /**
+     * Enter a parse tree produced by {@link qirParser#qir}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterQir(qirParser.QirContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#qir}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitQir(qirParser.QirContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#or}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterOr(qirParser.OrContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#or}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitOr(qirParser.OrContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#and}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterAnd(qirParser.AndContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#and}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitAnd(qirParser.AndContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#equal}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterEqual(qirParser.EqualContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#equal}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitEqual(qirParser.EqualContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#lower}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterLower(qirParser.LowerContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#lower}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitLower(qirParser.LowerContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#plus}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterPlus(qirParser.PlusContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#plus}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitPlus(qirParser.PlusContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#star}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterStar(qirParser.StarContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#star}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitStar(qirParser.StarContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#not}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterNot(qirParser.NotContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#not}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitNot(qirParser.NotContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#apply}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterApply(qirParser.ApplyContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#apply}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitApply(qirParser.ApplyContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#tdestr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterTdestr(qirParser.TdestrContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#tdestr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitTdestr(qirParser.TdestrContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#expr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterExpr(qirParser.ExprContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#expr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitExpr(qirParser.ExprContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#lambda}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterLambda(qirParser.LambdaContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#lambda}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitLambda(qirParser.LambdaContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#ifexpr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterIfexpr(qirParser.IfexprContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#ifexpr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitIfexpr(qirParser.IfexprContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#tcons}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterTcons(qirParser.TconsContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#tcons}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitTcons(qirParser.TconsContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#lcons}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterLcons(qirParser.LconsContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#lcons}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitLcons(qirParser.LconsContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#ldestr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterLdestr(qirParser.LdestrContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#ldestr}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitLdestr(qirParser.LdestrContext ctx);
+
+    /**
+     * Enter a parse tree produced by {@link qirParser#dataop}.
+     * 
+     * @param ctx the parse tree
+     */
+    void enterDataop(qirParser.DataopContext ctx);
+
+    /**
+     * Exit a parse tree produced by {@link qirParser#dataop}.
+     * 
+     * @param ctx the parse tree
+     */
+    void exitDataop(qirParser.DataopContext ctx);
+}
\ No newline at end of file
diff --git a/src/qir/parser/qirParser.java b/src/qir/parser/qirParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2254996583c89c50d5766c7eaf99606425af8bc
--- /dev/null
+++ b/src/qir/parser/qirParser.java
@@ -0,0 +1,1820 @@
+// Generated from qir.g4 by ANTLR 4.7
+
+package qir.parser;
+
+import java.util.Optional;
+import java.math.BigInteger;
+
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.source.SourceSection;
+
+import qir.ast.*;
+import qir.ast.data.*;
+import qir.ast.expression.*;
+import qir.ast.expression.arithmetic.*;
+import qir.ast.expression.logic.*;
+import qir.ast.expression.relational.*;
+import qir.ast.operator.*;
+import qir.util.QIRException;
+
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.misc.*;
+import org.antlr.v4.runtime.tree.*;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class qirParser extends Parser {
+	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
+	public static final int
+		T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, 
+		T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, 
+		T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, 
+		T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, 
+		T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, 
+		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, 
+		WS=46, COMMENT=47, LINE_COMMENT=48, IDENTIFIER=49, STRING=50, NUMBER=51, 
+		DOUBLE=52;
+	public static final int
+		RULE_qir = 0, RULE_or = 1, RULE_and = 2, RULE_equal = 3, RULE_lower = 4, 
+		RULE_plus = 5, RULE_star = 6, RULE_not = 7, RULE_apply = 8, RULE_tdestr = 9, 
+		RULE_expr = 10, RULE_lambda = 11, RULE_ifexpr = 12, RULE_tcons = 13, RULE_lcons = 14, 
+		RULE_ldestr = 15, RULE_dataop = 16;
+	public static final String[] ruleNames = {
+		"qir", "or", "and", "equal", "lower", "plus", "star", "not", "apply", 
+		"tdestr", "expr", "lambda", "ifexpr", "tcons", "lcons", "ldestr", "dataop"
+	};
+
+	private static final String[] _LITERAL_NAMES = {
+		null, "'||'", "'&&'", "'=='", "'<'", "'<='", "'+'", "'-'", "'*'", "'/'", 
+		"'%'", "'!'", "'@'", "'.'", "'External'", "'('", "')'", "'Table'", "','", 
+		"'BigNumber'", "'true'", "'false'", "'null'", "'fun'", "'#'", "'->'", 
+		"'if'", "'then'", "'else'", "'{'", "'='", "';'", "'}'", "'['", "']'", 
+		"'match'", "'with'", "'empty'", "'Project'", "'Scan'", "'Filter'", "'GroupBy'", 
+		"'SortBy'", "'Join'", "'LeftJoin'", "'RightJoin'"
+	};
+	private static final String[] _SYMBOLIC_NAMES = {
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, null, null, 
+		null, null, null, null, null, null, null, null, null, null, "WS", "COMMENT", 
+		"LINE_COMMENT", "IDENTIFIER", "STRING", "NUMBER", "DOUBLE"
+	};
+	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+	/**
+	 * @deprecated Use {@link #VOCABULARY} instead.
+	 */
+	@Deprecated
+	public static final String[] tokenNames;
+	static {
+		tokenNames = new String[_SYMBOLIC_NAMES.length];
+		for (int i = 0; i < tokenNames.length; i++) {
+			tokenNames[i] = VOCABULARY.getLiteralName(i);
+			if (tokenNames[i] == null) {
+				tokenNames[i] = VOCABULARY.getSymbolicName(i);
+			}
+
+			if (tokenNames[i] == null) {
+				tokenNames[i] = "<INVALID>";
+			}
+		}
+	}
+
+	@Override
+	@Deprecated
+	public String[] getTokenNames() {
+		return tokenNames;
+	}
+
+	@Override
+
+	public Vocabulary getVocabulary() {
+		return VOCABULARY;
+	}
+
+	@Override
+	public String getGrammarFileName() { return "qir.g4"; }
+
+	@Override
+	public String[] getRuleNames() { return ruleNames; }
+
+	@Override
+	public String getSerializedATN() { return _serializedATN; }
+
+	@Override
+	public ATN getATN() { return _ATN; }
+
+
+		private Source source;
+
+		private static final class BailoutErrorListener extends BaseErrorListener {
+		    private final Source source;
+		    BailoutErrorListener(Source source) {
+		        this.source = source;
+		    }
+		    @Override
+		    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+		        String location = "-- line " + line + " col " + (charPositionInLine + 1) + ": ";
+		        throw new QIRException("Parse error: " + location + msg);
+		    }
+		}
+
+		private final SourceSection srcFromToken(final Token begin, final Token end) {
+	        return source.createSection(begin.getStartIndex(), end.getStopIndex() - begin.getStartIndex());
+	    }
+
+		public void SemErr(Token token, String message) {
+		    int col = token.getCharPositionInLine() + 1;
+		    String location = "-- line " + token.getLine() + " col " + col + ": ";
+		    throw new QIRException("Parse error: " + location + message);
+		}
+
+	    public static QIRNode parseQIR(Source source) {
+	        qirLexer lexer = new qirLexer(CharStreams.fromString(source.getCharacters().toString()));
+	        qirParser parser = new qirParser(new CommonTokenStream(lexer));
+	        lexer.removeErrorListeners();
+	        parser.removeErrorListeners();
+	        BailoutErrorListener listener = new BailoutErrorListener(source);
+	        lexer.addErrorListener(listener);
+	        parser.addErrorListener(listener);
+	        parser.source = source;
+	        return parser.qir().result;
+	    }
+
+	public qirParser(TokenStream input) {
+		super(input);
+		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+	}
+	public static class QirContext extends ParserRuleContext {
+		public QIRNode result;
+		public OrContext or;
+		public OrContext or() {
+			return getRuleContext(OrContext.class,0);
+		}
+		public TerminalNode EOF() { return getToken(qirParser.EOF, 0); }
+		public QirContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_qir; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterQir(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitQir(this);
+		}
+	}
+
+	public final QirContext qir() throws RecognitionException {
+		QirContext _localctx = new QirContext(_ctx, getState());
+		enterRule(_localctx, 0, RULE_qir);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(34);
+			((QirContext)_localctx).or = or();
+			setState(35);
+			match(EOF);
+			 ((QirContext)_localctx).result =  ((QirContext)_localctx).or.result; 
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class OrContext extends ParserRuleContext {
+		public QIRNode result;
+		public AndContext t;
+		public AndContext and;
+		public List<AndContext> and() {
+			return getRuleContexts(AndContext.class);
+		}
+		public AndContext and(int i) {
+			return getRuleContext(AndContext.class,i);
+		}
+		public OrContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_or; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterOr(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitOr(this);
+		}
+	}
+
+	public final OrContext or() throws RecognitionException {
+		OrContext _localctx = new OrContext(_ctx, getState());
+		enterRule(_localctx, 2, RULE_or);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(38);
+			((OrContext)_localctx).t = ((OrContext)_localctx).and = and();
+			 ((OrContext)_localctx).result =  ((OrContext)_localctx).and.result; 
+			setState(46);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,0,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(40);
+					match(T__0);
+					setState(41);
+					((OrContext)_localctx).and = and();
+					 ((OrContext)_localctx).result =  QIROrNodeGen.create(srcFromToken((((OrContext)_localctx).t!=null?(((OrContext)_localctx).t.start):null), (((OrContext)_localctx).and!=null?(((OrContext)_localctx).and.start):null)), _localctx.result, ((OrContext)_localctx).and.result); 
+					}
+					} 
+				}
+				setState(48);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,0,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class AndContext extends ParserRuleContext {
+		public QIRNode result;
+		public EqualContext t;
+		public EqualContext equal;
+		public List<EqualContext> equal() {
+			return getRuleContexts(EqualContext.class);
+		}
+		public EqualContext equal(int i) {
+			return getRuleContext(EqualContext.class,i);
+		}
+		public AndContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_and; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterAnd(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitAnd(this);
+		}
+	}
+
+	public final AndContext and() throws RecognitionException {
+		AndContext _localctx = new AndContext(_ctx, getState());
+		enterRule(_localctx, 4, RULE_and);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(49);
+			((AndContext)_localctx).t = ((AndContext)_localctx).equal = equal();
+			 ((AndContext)_localctx).result =  ((AndContext)_localctx).equal.result; 
+			setState(57);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,1,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(51);
+					match(T__1);
+					setState(52);
+					((AndContext)_localctx).equal = equal();
+					 ((AndContext)_localctx).result =  QIRAndNodeGen.create(srcFromToken((((AndContext)_localctx).t!=null?(((AndContext)_localctx).t.start):null), (((AndContext)_localctx).equal!=null?(((AndContext)_localctx).equal.start):null)), _localctx.result, ((AndContext)_localctx).equal.result); 
+					}
+					} 
+				}
+				setState(59);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,1,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class EqualContext extends ParserRuleContext {
+		public QIRNode result;
+		public LowerContext t;
+		public LowerContext lower;
+		public List<LowerContext> lower() {
+			return getRuleContexts(LowerContext.class);
+		}
+		public LowerContext lower(int i) {
+			return getRuleContext(LowerContext.class,i);
+		}
+		public EqualContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_equal; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterEqual(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitEqual(this);
+		}
+	}
+
+	public final EqualContext equal() throws RecognitionException {
+		EqualContext _localctx = new EqualContext(_ctx, getState());
+		enterRule(_localctx, 6, RULE_equal);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(60);
+			((EqualContext)_localctx).t = ((EqualContext)_localctx).lower = lower();
+			 ((EqualContext)_localctx).result =  ((EqualContext)_localctx).lower.result; 
+			setState(68);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,2,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(62);
+					match(T__2);
+					setState(63);
+					((EqualContext)_localctx).lower = lower();
+					 ((EqualContext)_localctx).result =  QIREqualNodeGen.create(srcFromToken((((EqualContext)_localctx).t!=null?(((EqualContext)_localctx).t.start):null), (((EqualContext)_localctx).lower!=null?(((EqualContext)_localctx).lower.start):null)), _localctx.result, ((EqualContext)_localctx).lower.result); 
+					}
+					} 
+				}
+				setState(70);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,2,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class LowerContext extends ParserRuleContext {
+		public QIRNode result;
+		public PlusContext t;
+		public PlusContext plus;
+		public List<PlusContext> plus() {
+			return getRuleContexts(PlusContext.class);
+		}
+		public PlusContext plus(int i) {
+			return getRuleContext(PlusContext.class,i);
+		}
+		public LowerContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_lower; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterLower(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitLower(this);
+		}
+	}
+
+	public final LowerContext lower() throws RecognitionException {
+		LowerContext _localctx = new LowerContext(_ctx, getState());
+		enterRule(_localctx, 8, RULE_lower);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(71);
+			((LowerContext)_localctx).t = ((LowerContext)_localctx).plus = plus();
+			 ((LowerContext)_localctx).result =  ((LowerContext)_localctx).plus.result; 
+			setState(81);
+			_errHandler.sync(this);
+			switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) {
+			case 1:
+				{
+				setState(73);
+				match(T__3);
+				setState(74);
+				((LowerContext)_localctx).plus = plus();
+				 ((LowerContext)_localctx).result =  QIRLowerThanNodeGen.create(srcFromToken((((LowerContext)_localctx).t!=null?(((LowerContext)_localctx).t.start):null), (((LowerContext)_localctx).plus!=null?(((LowerContext)_localctx).plus.start):null)), _localctx.result, ((LowerContext)_localctx).plus.result); 
+				}
+				break;
+			case 2:
+				{
+				setState(77);
+				match(T__4);
+				setState(78);
+				((LowerContext)_localctx).plus = plus();
+				 ((LowerContext)_localctx).result =  QIRLowerOrEqualNodeGen.create(srcFromToken((((LowerContext)_localctx).t!=null?(((LowerContext)_localctx).t.start):null), (((LowerContext)_localctx).plus!=null?(((LowerContext)_localctx).plus.start):null)), _localctx.result, ((LowerContext)_localctx).plus.result); 
+				}
+				break;
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class PlusContext extends ParserRuleContext {
+		public QIRNode result;
+		public StarContext t;
+		public StarContext star;
+		public List<StarContext> star() {
+			return getRuleContexts(StarContext.class);
+		}
+		public StarContext star(int i) {
+			return getRuleContext(StarContext.class,i);
+		}
+		public PlusContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_plus; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterPlus(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitPlus(this);
+		}
+	}
+
+	public final PlusContext plus() throws RecognitionException {
+		PlusContext _localctx = new PlusContext(_ctx, getState());
+		enterRule(_localctx, 10, RULE_plus);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(83);
+			((PlusContext)_localctx).t = ((PlusContext)_localctx).star = star();
+			 ((PlusContext)_localctx).result =  ((PlusContext)_localctx).star.result; 
+			setState(95);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					setState(93);
+					_errHandler.sync(this);
+					switch (_input.LA(1)) {
+					case T__5:
+						{
+						setState(85);
+						match(T__5);
+						setState(86);
+						((PlusContext)_localctx).star = star();
+						 ((PlusContext)_localctx).result =  QIRPlusNodeGen.create(srcFromToken((((PlusContext)_localctx).t!=null?(((PlusContext)_localctx).t.start):null), (((PlusContext)_localctx).star!=null?(((PlusContext)_localctx).star.start):null)), _localctx.result, ((PlusContext)_localctx).star.result); 
+						}
+						break;
+					case T__6:
+						{
+						setState(89);
+						match(T__6);
+						setState(90);
+						((PlusContext)_localctx).star = star();
+						 ((PlusContext)_localctx).result =  QIRMinusNodeGen.create(srcFromToken((((PlusContext)_localctx).t!=null?(((PlusContext)_localctx).t.start):null), (((PlusContext)_localctx).star!=null?(((PlusContext)_localctx).star.start):null)), _localctx.result, ((PlusContext)_localctx).star.result); 
+						}
+						break;
+					default:
+						throw new NoViableAltException(this);
+					}
+					} 
+				}
+				setState(97);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class StarContext extends ParserRuleContext {
+		public QIRNode result;
+		public NotContext t;
+		public NotContext not;
+		public List<NotContext> not() {
+			return getRuleContexts(NotContext.class);
+		}
+		public NotContext not(int i) {
+			return getRuleContext(NotContext.class,i);
+		}
+		public StarContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_star; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterStar(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitStar(this);
+		}
+	}
+
+	public final StarContext star() throws RecognitionException {
+		StarContext _localctx = new StarContext(_ctx, getState());
+		enterRule(_localctx, 12, RULE_star);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(98);
+			((StarContext)_localctx).t = ((StarContext)_localctx).not = not();
+			 ((StarContext)_localctx).result =  ((StarContext)_localctx).not.result; 
+			setState(114);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					setState(112);
+					_errHandler.sync(this);
+					switch (_input.LA(1)) {
+					case T__7:
+						{
+						setState(100);
+						match(T__7);
+						setState(101);
+						((StarContext)_localctx).not = not();
+						 ((StarContext)_localctx).result =  QIRStarNodeGen.create(srcFromToken((((StarContext)_localctx).t!=null?(((StarContext)_localctx).t.start):null), (((StarContext)_localctx).not!=null?(((StarContext)_localctx).not.start):null)), _localctx.result, ((StarContext)_localctx).not.result); 
+						}
+						break;
+					case T__8:
+						{
+						setState(104);
+						match(T__8);
+						setState(105);
+						((StarContext)_localctx).not = not();
+						 ((StarContext)_localctx).result =  QIRDivNodeGen.create(srcFromToken((((StarContext)_localctx).t!=null?(((StarContext)_localctx).t.start):null), (((StarContext)_localctx).not!=null?(((StarContext)_localctx).not.start):null)), _localctx.result, ((StarContext)_localctx).not.result); 
+						}
+						break;
+					case T__9:
+						{
+						setState(108);
+						match(T__9);
+						setState(109);
+						((StarContext)_localctx).not = not();
+						 ((StarContext)_localctx).result =  QIRModNodeGen.create(srcFromToken((((StarContext)_localctx).t!=null?(((StarContext)_localctx).t.start):null), (((StarContext)_localctx).not!=null?(((StarContext)_localctx).not.start):null)), _localctx.result, ((StarContext)_localctx).not.result); 
+						}
+						break;
+					default:
+						throw new NoViableAltException(this);
+					}
+					} 
+				}
+				setState(116);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class NotContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token op;
+		public ApplyContext apply;
+		public ApplyContext apply() {
+			return getRuleContext(ApplyContext.class,0);
+		}
+		public NotContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_not; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterNot(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitNot(this);
+		}
+	}
+
+	public final NotContext not() throws RecognitionException {
+		NotContext _localctx = new NotContext(_ctx, getState());
+		enterRule(_localctx, 14, RULE_not);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			 Optional<Token> t = Optional.empty(); 
+			setState(120);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			if (_la==T__10) {
+				{
+				setState(118);
+				((NotContext)_localctx).op = match(T__10);
+				 t = Optional.of(((NotContext)_localctx).op); 
+				}
+			}
+
+			setState(122);
+			((NotContext)_localctx).apply = apply();
+			 ((NotContext)_localctx).result =  t.isPresent() ? QIRNotNodeGen.create(srcFromToken(t.get(), (((NotContext)_localctx).apply!=null?(((NotContext)_localctx).apply.start):null)), ((NotContext)_localctx).apply.result) : ((NotContext)_localctx).apply.result; 
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ApplyContext extends ParserRuleContext {
+		public QIRNode result;
+		public TdestrContext t;
+		public TdestrContext tdestr;
+		public List<TdestrContext> tdestr() {
+			return getRuleContexts(TdestrContext.class);
+		}
+		public TdestrContext tdestr(int i) {
+			return getRuleContext(TdestrContext.class,i);
+		}
+		public ApplyContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_apply; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterApply(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitApply(this);
+		}
+	}
+
+	public final ApplyContext apply() throws RecognitionException {
+		ApplyContext _localctx = new ApplyContext(_ctx, getState());
+		enterRule(_localctx, 16, RULE_apply);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(125);
+			((ApplyContext)_localctx).t = ((ApplyContext)_localctx).tdestr = tdestr();
+			 ((ApplyContext)_localctx).result =  ((ApplyContext)_localctx).tdestr.result; 
+			setState(133);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(127);
+					match(T__11);
+					setState(128);
+					((ApplyContext)_localctx).tdestr = tdestr();
+					 ((ApplyContext)_localctx).result =  new QIRApply(srcFromToken((((ApplyContext)_localctx).t!=null?(((ApplyContext)_localctx).t.start):null), (((ApplyContext)_localctx).tdestr!=null?(((ApplyContext)_localctx).tdestr.start):null)), _localctx.result, ((ApplyContext)_localctx).tdestr.result); 
+					}
+					} 
+				}
+				setState(135);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class TdestrContext extends ParserRuleContext {
+		public QIRNode result;
+		public ExprContext t;
+		public ExprContext expr;
+		public Token IDENTIFIER;
+		public ExprContext expr() {
+			return getRuleContext(ExprContext.class,0);
+		}
+		public List<TerminalNode> IDENTIFIER() { return getTokens(qirParser.IDENTIFIER); }
+		public TerminalNode IDENTIFIER(int i) {
+			return getToken(qirParser.IDENTIFIER, i);
+		}
+		public TdestrContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_tdestr; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterTdestr(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitTdestr(this);
+		}
+	}
+
+	public final TdestrContext tdestr() throws RecognitionException {
+		TdestrContext _localctx = new TdestrContext(_ctx, getState());
+		enterRule(_localctx, 18, RULE_tdestr);
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(136);
+			((TdestrContext)_localctx).t = ((TdestrContext)_localctx).expr = expr();
+			 ((TdestrContext)_localctx).result =  ((TdestrContext)_localctx).expr.result; 
+			setState(143);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(138);
+					match(T__12);
+					setState(139);
+					((TdestrContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+					 ((TdestrContext)_localctx).result =  new QIRRdestr(srcFromToken((((TdestrContext)_localctx).t!=null?(((TdestrContext)_localctx).t.start):null), ((TdestrContext)_localctx).IDENTIFIER), _localctx.result, ((TdestrContext)_localctx).IDENTIFIER.getText()); 
+					}
+					} 
+				}
+				setState(145);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ExprContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token IDENTIFIER;
+		public LambdaContext lambda;
+		public IfexprContext ifexpr;
+		public TconsContext tcons;
+		public LconsContext lcons;
+		public LdestrContext ldestr;
+		public Token t;
+		public Token end;
+		public OrContext tableName;
+		public OrContext dbName;
+		public OrContext configFile;
+		public OrContext schemaName;
+		public Token NUMBER;
+		public Token DOUBLE;
+		public Token STRING;
+		public DataopContext dataop;
+		public ExprContext expr;
+		public TerminalNode IDENTIFIER() { return getToken(qirParser.IDENTIFIER, 0); }
+		public LambdaContext lambda() {
+			return getRuleContext(LambdaContext.class,0);
+		}
+		public IfexprContext ifexpr() {
+			return getRuleContext(IfexprContext.class,0);
+		}
+		public TconsContext tcons() {
+			return getRuleContext(TconsContext.class,0);
+		}
+		public LconsContext lcons() {
+			return getRuleContext(LconsContext.class,0);
+		}
+		public LdestrContext ldestr() {
+			return getRuleContext(LdestrContext.class,0);
+		}
+		public TerminalNode NUMBER() { return getToken(qirParser.NUMBER, 0); }
+		public TerminalNode DOUBLE() { return getToken(qirParser.DOUBLE, 0); }
+		public TerminalNode STRING() { return getToken(qirParser.STRING, 0); }
+		public DataopContext dataop() {
+			return getRuleContext(DataopContext.class,0);
+		}
+		public ExprContext expr() {
+			return getRuleContext(ExprContext.class,0);
+		}
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public ExprContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_expr; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterExpr(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitExpr(this);
+		}
+	}
+
+	public final ExprContext expr() throws RecognitionException {
+		ExprContext _localctx = new ExprContext(_ctx, getState());
+		enterRule(_localctx, 20, RULE_expr);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(205);
+			_errHandler.sync(this);
+			switch (_input.LA(1)) {
+			case IDENTIFIER:
+				{
+				setState(146);
+				((ExprContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+				 ((ExprContext)_localctx).result =  new QIRVariable(srcFromToken(((ExprContext)_localctx).IDENTIFIER, ((ExprContext)_localctx).IDENTIFIER), ((ExprContext)_localctx).IDENTIFIER.getText()); 
+				}
+				break;
+			case T__22:
+				{
+				setState(148);
+				((ExprContext)_localctx).lambda = lambda();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).lambda.result; 
+				}
+				break;
+			case T__25:
+				{
+				setState(151);
+				((ExprContext)_localctx).ifexpr = ifexpr();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).ifexpr.result; 
+				}
+				break;
+			case T__28:
+				{
+				setState(154);
+				((ExprContext)_localctx).tcons = tcons();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).tcons.result; 
+				}
+				break;
+			case T__32:
+				{
+				setState(157);
+				((ExprContext)_localctx).lcons = lcons();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).lcons.result; 
+				}
+				break;
+			case T__34:
+				{
+				setState(160);
+				((ExprContext)_localctx).ldestr = ldestr();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).ldestr.result; 
+				}
+				break;
+			case T__13:
+				{
+				setState(163);
+				((ExprContext)_localctx).t = match(T__13);
+				setState(164);
+				match(T__14);
+				setState(165);
+				((ExprContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+				setState(166);
+				((ExprContext)_localctx).end = match(T__15);
+				 ((ExprContext)_localctx).result =  new QIRExternal(srcFromToken(((ExprContext)_localctx).t, ((ExprContext)_localctx).end), ((ExprContext)_localctx).IDENTIFIER.getText()); 
+				}
+				break;
+			case T__16:
+				{
+				setState(168);
+				((ExprContext)_localctx).t = match(T__16);
+				setState(169);
+				match(T__14);
+				setState(170);
+				((ExprContext)_localctx).tableName = or();
+				setState(171);
+				match(T__17);
+				setState(172);
+				((ExprContext)_localctx).dbName = or();
+				setState(173);
+				match(T__17);
+				setState(174);
+				((ExprContext)_localctx).configFile = or();
+				setState(175);
+				match(T__17);
+				setState(176);
+				((ExprContext)_localctx).schemaName = or();
+				setState(177);
+				((ExprContext)_localctx).end = match(T__15);
+				 ((ExprContext)_localctx).result =  new QIRTable(srcFromToken(((ExprContext)_localctx).t, ((ExprContext)_localctx).end), ((ExprContext)_localctx).tableName.result, ((ExprContext)_localctx).dbName.result, ((ExprContext)_localctx).configFile.result, ((ExprContext)_localctx).schemaName.result); 
+				}
+				break;
+			case T__18:
+				{
+				setState(180);
+				((ExprContext)_localctx).t = match(T__18);
+				setState(181);
+				match(T__14);
+				setState(182);
+				((ExprContext)_localctx).NUMBER = match(NUMBER);
+				setState(183);
+				((ExprContext)_localctx).end = match(T__15);
+				 ((ExprContext)_localctx).result =  new QIRBigNumber(srcFromToken(((ExprContext)_localctx).t, ((ExprContext)_localctx).end), new BigInteger(((ExprContext)_localctx).NUMBER.getText())); 
+				}
+				break;
+			case T__19:
+				{
+				setState(185);
+				match(T__19);
+				 ((ExprContext)_localctx).result =  QIRBoolean.TRUE; 
+				}
+				break;
+			case T__20:
+				{
+				setState(187);
+				match(T__20);
+				 ((ExprContext)_localctx).result =  QIRBoolean.FALSE; 
+				}
+				break;
+			case NUMBER:
+				{
+				setState(189);
+				((ExprContext)_localctx).NUMBER = match(NUMBER);
+				 ((ExprContext)_localctx).result =  new QIRNumber(srcFromToken(((ExprContext)_localctx).NUMBER, ((ExprContext)_localctx).NUMBER), Long.parseLong(((ExprContext)_localctx).NUMBER.getText())); 
+				}
+				break;
+			case DOUBLE:
+				{
+				setState(191);
+				((ExprContext)_localctx).DOUBLE = match(DOUBLE);
+				 ((ExprContext)_localctx).result =  new QIRDouble(srcFromToken(((ExprContext)_localctx).DOUBLE, ((ExprContext)_localctx).DOUBLE), Double.parseDouble(((ExprContext)_localctx).DOUBLE.getText())); 
+				}
+				break;
+			case T__21:
+				{
+				setState(193);
+				match(T__21);
+				 ((ExprContext)_localctx).result =  QIRNull.getInstance(); 
+				}
+				break;
+			case STRING:
+				{
+				setState(195);
+				((ExprContext)_localctx).STRING = match(STRING);
+				 ((ExprContext)_localctx).result =  new QIRString(srcFromToken(((ExprContext)_localctx).STRING, ((ExprContext)_localctx).STRING), ((ExprContext)_localctx).STRING.getText()); 
+				}
+				break;
+			case T__9:
+				{
+				setState(197);
+				((ExprContext)_localctx).dataop = dataop();
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).dataop.result; 
+				}
+				break;
+			case T__14:
+				{
+				setState(200);
+				match(T__14);
+				setState(201);
+				((ExprContext)_localctx).expr = expr();
+				setState(202);
+				match(T__15);
+				 ((ExprContext)_localctx).result =  ((ExprContext)_localctx).expr.result; 
+				}
+				break;
+			default:
+				throw new NoViableAltException(this);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class LambdaContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public Token IDENTIFIER;
+		public Token var;
+		public OrContext or;
+		public OrContext or() {
+			return getRuleContext(OrContext.class,0);
+		}
+		public List<TerminalNode> IDENTIFIER() { return getTokens(qirParser.IDENTIFIER); }
+		public TerminalNode IDENTIFIER(int i) {
+			return getToken(qirParser.IDENTIFIER, i);
+		}
+		public LambdaContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_lambda; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterLambda(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitLambda(this);
+		}
+	}
+
+	public final LambdaContext lambda() throws RecognitionException {
+		LambdaContext _localctx = new LambdaContext(_ctx, getState());
+		enterRule(_localctx, 22, RULE_lambda);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(207);
+			((LambdaContext)_localctx).t = match(T__22);
+			 String funName = null; 
+			setState(212);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			if (_la==T__23) {
+				{
+				setState(209);
+				match(T__23);
+				setState(210);
+				((LambdaContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+				 funName = ((LambdaContext)_localctx).IDENTIFIER.getText(); 
+				}
+			}
+
+			setState(214);
+			((LambdaContext)_localctx).var = match(IDENTIFIER);
+			setState(215);
+			match(T__24);
+			setState(216);
+			((LambdaContext)_localctx).or = or();
+			 ((LambdaContext)_localctx).result =  new QIRLambda(srcFromToken(((LambdaContext)_localctx).t, (((LambdaContext)_localctx).or!=null?(((LambdaContext)_localctx).or.start):null)), funName, new QIRVariable(srcFromToken(((LambdaContext)_localctx).var, ((LambdaContext)_localctx).var), ((LambdaContext)_localctx).var.getText()), ((LambdaContext)_localctx).or.result, new FrameDescriptor()); 
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class IfexprContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public OrContext cond;
+		public OrContext thenNode;
+		public OrContext elseNode;
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public IfexprContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_ifexpr; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterIfexpr(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitIfexpr(this);
+		}
+	}
+
+	public final IfexprContext ifexpr() throws RecognitionException {
+		IfexprContext _localctx = new IfexprContext(_ctx, getState());
+		enterRule(_localctx, 24, RULE_ifexpr);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(219);
+			((IfexprContext)_localctx).t = match(T__25);
+			setState(220);
+			((IfexprContext)_localctx).cond = or();
+			setState(221);
+			match(T__26);
+			setState(222);
+			((IfexprContext)_localctx).thenNode = or();
+			setState(223);
+			match(T__27);
+			setState(224);
+			((IfexprContext)_localctx).elseNode = or();
+			 ((IfexprContext)_localctx).result =  new QIRIf(srcFromToken(((IfexprContext)_localctx).t, (((IfexprContext)_localctx).elseNode!=null?(((IfexprContext)_localctx).elseNode.start):null)), ((IfexprContext)_localctx).cond.result, ((IfexprContext)_localctx).thenNode.result, ((IfexprContext)_localctx).elseNode.result); 
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class TconsContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public Token IDENTIFIER;
+		public OrContext or;
+		public List<TerminalNode> IDENTIFIER() { return getTokens(qirParser.IDENTIFIER); }
+		public TerminalNode IDENTIFIER(int i) {
+			return getToken(qirParser.IDENTIFIER, i);
+		}
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public TconsContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_tcons; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterTcons(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitTcons(this);
+		}
+	}
+
+	public final TconsContext tcons() throws RecognitionException {
+		TconsContext _localctx = new TconsContext(_ctx, getState());
+		enterRule(_localctx, 26, RULE_tcons);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(227);
+			((TconsContext)_localctx).t = match(T__28);
+			 ((TconsContext)_localctx).result =  QIRRnil.getInstance(); 
+			setState(244);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			if (_la==IDENTIFIER) {
+				{
+				setState(229);
+				((TconsContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+				setState(230);
+				match(T__29);
+				setState(231);
+				((TconsContext)_localctx).or = or();
+				 ((TconsContext)_localctx).result =  new QIRRcons(srcFromToken(((TconsContext)_localctx).t, (((TconsContext)_localctx).or!=null?(((TconsContext)_localctx).or.start):null)), ((TconsContext)_localctx).IDENTIFIER.getText(), ((TconsContext)_localctx).or.result, _localctx.result); 
+				setState(241);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+				while (_la==T__30) {
+					{
+					{
+					setState(233);
+					match(T__30);
+					setState(234);
+					((TconsContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+					setState(235);
+					match(T__29);
+					setState(236);
+					((TconsContext)_localctx).or = or();
+					 ((TconsContext)_localctx).result =  new QIRRcons(srcFromToken(((TconsContext)_localctx).t, (((TconsContext)_localctx).or!=null?(((TconsContext)_localctx).or.start):null)), ((TconsContext)_localctx).IDENTIFIER.getText(), ((TconsContext)_localctx).or.result, _localctx.result); 
+					}
+					}
+					setState(243);
+					_errHandler.sync(this);
+					_la = _input.LA(1);
+				}
+				}
+			}
+
+			setState(246);
+			match(T__31);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class LconsContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public OrContext or;
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public LconsContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_lcons; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterLcons(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitLcons(this);
+		}
+	}
+
+	public final LconsContext lcons() throws RecognitionException {
+		LconsContext _localctx = new LconsContext(_ctx, getState());
+		enterRule(_localctx, 28, RULE_lcons);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(248);
+			((LconsContext)_localctx).t = match(T__32);
+			 ((LconsContext)_localctx).result =  QIRLnil.getInstance(); 
+			setState(261);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__9) | (1L << T__10) | (1L << T__13) | (1L << T__14) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__25) | (1L << T__28) | (1L << T__32) | (1L << T__34) | (1L << IDENTIFIER) | (1L << STRING) | (1L << NUMBER) | (1L << DOUBLE))) != 0)) {
+				{
+				setState(250);
+				((LconsContext)_localctx).or = or();
+				 ((LconsContext)_localctx).result =  new QIRLcons(srcFromToken(((LconsContext)_localctx).t, (((LconsContext)_localctx).or!=null?(((LconsContext)_localctx).or.start):null)), ((LconsContext)_localctx).or.result, _localctx.result); 
+				setState(258);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+				while (_la==T__30) {
+					{
+					{
+					setState(252);
+					match(T__30);
+					setState(253);
+					((LconsContext)_localctx).or = or();
+					 ((LconsContext)_localctx).result =  new QIRLcons(srcFromToken(((LconsContext)_localctx).t, (((LconsContext)_localctx).or!=null?(((LconsContext)_localctx).or.start):null)), ((LconsContext)_localctx).or.result, _localctx.result); 
+					}
+					}
+					setState(260);
+					_errHandler.sync(this);
+					_la = _input.LA(1);
+				}
+				}
+			}
+
+			setState(263);
+			match(T__33);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class LdestrContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public OrContext list;
+		public OrContext ifEmpty;
+		public OrContext handler;
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public LdestrContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_ldestr; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterLdestr(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitLdestr(this);
+		}
+	}
+
+	public final LdestrContext ldestr() throws RecognitionException {
+		LdestrContext _localctx = new LdestrContext(_ctx, getState());
+		enterRule(_localctx, 30, RULE_ldestr);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(265);
+			((LdestrContext)_localctx).t = match(T__34);
+			setState(266);
+			((LdestrContext)_localctx).list = or();
+			setState(267);
+			match(T__35);
+			setState(268);
+			match(T__36);
+			setState(269);
+			match(T__24);
+			setState(270);
+			((LdestrContext)_localctx).ifEmpty = or();
+			setState(271);
+			match(T__27);
+			setState(272);
+			match(T__24);
+			setState(273);
+			((LdestrContext)_localctx).handler = or();
+			 ((LdestrContext)_localctx).result =  new QIRLdestr(srcFromToken(((LdestrContext)_localctx).t, (((LdestrContext)_localctx).handler!=null?(((LdestrContext)_localctx).handler.start):null)), ((LdestrContext)_localctx).list.result, ((LdestrContext)_localctx).ifEmpty.result, ((LdestrContext)_localctx).handler.result); 
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class DataopContext extends ParserRuleContext {
+		public QIRNode result;
+		public Token t;
+		public OrContext formatter;
+		public OrContext child;
+		public Token end;
+		public OrContext filter;
+		public OrContext group;
+		public OrContext sort;
+		public OrContext isAscending;
+		public OrContext left;
+		public OrContext right;
+		public Token IDENTIFIER;
+		public OrContext arg;
+		public TerminalNode IDENTIFIER() { return getToken(qirParser.IDENTIFIER, 0); }
+		public List<OrContext> or() {
+			return getRuleContexts(OrContext.class);
+		}
+		public OrContext or(int i) {
+			return getRuleContext(OrContext.class,i);
+		}
+		public DataopContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_dataop; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).enterDataop(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof qirListener ) ((qirListener)listener).exitDataop(this);
+		}
+	}
+
+	public final DataopContext dataop() throws RecognitionException {
+		DataopContext _localctx = new DataopContext(_ctx, getState());
+		enterRule(_localctx, 32, RULE_dataop);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(276);
+			((DataopContext)_localctx).t = match(T__9);
+			setState(365);
+			_errHandler.sync(this);
+			switch (_input.LA(1)) {
+			case T__37:
+				{
+				setState(277);
+				match(T__37);
+				setState(278);
+				match(T__14);
+				setState(279);
+				((DataopContext)_localctx).formatter = or();
+				setState(280);
+				match(T__17);
+				setState(281);
+				((DataopContext)_localctx).child = or();
+				setState(282);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRProject(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).formatter.result, ((DataopContext)_localctx).child.result); 
+				}
+				break;
+			case T__38:
+				{
+				setState(285);
+				match(T__38);
+				setState(286);
+				match(T__14);
+				setState(287);
+				((DataopContext)_localctx).child = or();
+				setState(288);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRScan(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).child.result); 
+				}
+				break;
+			case T__39:
+				{
+				setState(291);
+				match(T__39);
+				setState(292);
+				match(T__14);
+				setState(293);
+				((DataopContext)_localctx).filter = or();
+				setState(294);
+				match(T__17);
+				setState(295);
+				((DataopContext)_localctx).child = or();
+				setState(296);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRFilter(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).filter.result, ((DataopContext)_localctx).child.result); 
+				}
+				break;
+			case T__40:
+				{
+				setState(299);
+				match(T__40);
+				setState(300);
+				match(T__14);
+				setState(301);
+				((DataopContext)_localctx).group = or();
+				setState(302);
+				match(T__17);
+				setState(303);
+				((DataopContext)_localctx).child = or();
+				setState(304);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRGroupBy(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).group.result, ((DataopContext)_localctx).child.result); 
+				}
+				break;
+			case T__41:
+				{
+				setState(307);
+				match(T__41);
+				setState(308);
+				match(T__14);
+				setState(309);
+				((DataopContext)_localctx).sort = or();
+				setState(310);
+				match(T__17);
+				setState(311);
+				((DataopContext)_localctx).isAscending = or();
+				setState(312);
+				match(T__17);
+				setState(313);
+				((DataopContext)_localctx).child = or();
+				setState(314);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRSortBy(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).sort.result, ((DataopContext)_localctx).isAscending.result, ((DataopContext)_localctx).child.result); 
+				}
+				break;
+			case T__42:
+				{
+				setState(317);
+				match(T__42);
+				setState(318);
+				match(T__14);
+				setState(319);
+				((DataopContext)_localctx).filter = or();
+				setState(320);
+				match(T__17);
+				setState(321);
+				((DataopContext)_localctx).left = or();
+				setState(322);
+				match(T__17);
+				setState(323);
+				((DataopContext)_localctx).right = or();
+				setState(324);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRJoin(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).filter.result, ((DataopContext)_localctx).left.result, ((DataopContext)_localctx).right.result); 
+				}
+				break;
+			case T__43:
+				{
+				setState(327);
+				match(T__43);
+				setState(328);
+				match(T__14);
+				setState(329);
+				((DataopContext)_localctx).filter = or();
+				setState(330);
+				match(T__17);
+				setState(331);
+				((DataopContext)_localctx).left = or();
+				setState(332);
+				match(T__17);
+				setState(333);
+				((DataopContext)_localctx).right = or();
+				setState(334);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRLeftJoin(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).filter.result, ((DataopContext)_localctx).left.result, ((DataopContext)_localctx).right.result); 
+				}
+				break;
+			case T__44:
+				{
+				setState(337);
+				match(T__44);
+				setState(338);
+				match(T__14);
+				setState(339);
+				((DataopContext)_localctx).filter = or();
+				setState(340);
+				match(T__17);
+				setState(341);
+				((DataopContext)_localctx).left = or();
+				setState(342);
+				match(T__17);
+				setState(343);
+				((DataopContext)_localctx).right = or();
+				setState(344);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new QIRRightJoin(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).filter.result, ((DataopContext)_localctx).left.result, ((DataopContext)_localctx).right.result); 
+				}
+				break;
+			case IDENTIFIER:
+				{
+				setState(347);
+				((DataopContext)_localctx).IDENTIFIER = match(IDENTIFIER);
+				setState(348);
+				match(T__14);
+				 final List<QIRNode> args = new ArrayList<>(); 
+				setState(361);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__9) | (1L << T__10) | (1L << T__13) | (1L << T__14) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__25) | (1L << T__28) | (1L << T__32) | (1L << T__34) | (1L << IDENTIFIER) | (1L << STRING) | (1L << NUMBER) | (1L << DOUBLE))) != 0)) {
+					{
+					setState(350);
+					((DataopContext)_localctx).arg = or();
+					 args.add(((DataopContext)_localctx).arg.result); 
+					setState(358);
+					_errHandler.sync(this);
+					_la = _input.LA(1);
+					while (_la==T__17) {
+						{
+						{
+						setState(352);
+						match(T__17);
+						setState(353);
+						((DataopContext)_localctx).arg = or();
+						 args.add(((DataopContext)_localctx).arg.result); 
+						}
+						}
+						setState(360);
+						_errHandler.sync(this);
+						_la = _input.LA(1);
+					}
+					}
+				}
+
+				setState(363);
+				((DataopContext)_localctx).end = match(T__15);
+				 ((DataopContext)_localctx).result =  new ExternalOperator(srcFromToken(((DataopContext)_localctx).t, ((DataopContext)_localctx).end), ((DataopContext)_localctx).IDENTIFIER.getText(), args); 
+				}
+				break;
+			default:
+				throw new NoViableAltException(this);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static final String _serializedATN =
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\66\u0172\4\2\t\2"+
+		"\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
+		"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
+		"\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\7\3/\n\3\f\3\16\3\62\13\3\3\4"+
+		"\3\4\3\4\3\4\3\4\3\4\7\4:\n\4\f\4\16\4=\13\4\3\5\3\5\3\5\3\5\3\5\3\5\7"+
+		"\5E\n\5\f\5\16\5H\13\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6T\n"+
+		"\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\7\7`\n\7\f\7\16\7c\13\7\3\b"+
+		"\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\7\bs\n\b\f\b\16\b"+
+		"v\13\b\3\t\3\t\3\t\5\t{\n\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u0086"+
+		"\n\n\f\n\16\n\u0089\13\n\3\13\3\13\3\13\3\13\3\13\7\13\u0090\n\13\f\13"+
+		"\16\13\u0093\13\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f"+
+		"\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3"+
+		"\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f"+
+		"\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\5\f\u00d0\n\f\3\r\3\r\3\r"+
+		"\3\r\3\r\5\r\u00d7\n\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3"+
+		"\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3"+
+		"\17\7\17\u00f2\n\17\f\17\16\17\u00f5\13\17\5\17\u00f7\n\17\3\17\3\17\3"+
+		"\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\7\20\u0103\n\20\f\20\16\20\u0106"+
+		"\13\20\5\20\u0108\n\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3"+
+		"\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+
+		"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+
+		"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+
+		"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+
+		"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+
+		"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\7"+
+		"\22\u0167\n\22\f\22\16\22\u016a\13\22\5\22\u016c\n\22\3\22\3\22\5\22\u0170"+
+		"\n\22\3\22\2\2\23\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"\2\2\2\u018c"+
+		"\2$\3\2\2\2\4(\3\2\2\2\6\63\3\2\2\2\b>\3\2\2\2\nI\3\2\2\2\fU\3\2\2\2\16"+
+		"d\3\2\2\2\20w\3\2\2\2\22\177\3\2\2\2\24\u008a\3\2\2\2\26\u00cf\3\2\2\2"+
+		"\30\u00d1\3\2\2\2\32\u00dd\3\2\2\2\34\u00e5\3\2\2\2\36\u00fa\3\2\2\2 "+
+		"\u010b\3\2\2\2\"\u0116\3\2\2\2$%\5\4\3\2%&\7\2\2\3&\'\b\2\1\2\'\3\3\2"+
+		"\2\2()\5\6\4\2)\60\b\3\1\2*+\7\3\2\2+,\5\6\4\2,-\b\3\1\2-/\3\2\2\2.*\3"+
+		"\2\2\2/\62\3\2\2\2\60.\3\2\2\2\60\61\3\2\2\2\61\5\3\2\2\2\62\60\3\2\2"+
+		"\2\63\64\5\b\5\2\64;\b\4\1\2\65\66\7\4\2\2\66\67\5\b\5\2\678\b\4\1\28"+
+		":\3\2\2\29\65\3\2\2\2:=\3\2\2\2;9\3\2\2\2;<\3\2\2\2<\7\3\2\2\2=;\3\2\2"+
+		"\2>?\5\n\6\2?F\b\5\1\2@A\7\5\2\2AB\5\n\6\2BC\b\5\1\2CE\3\2\2\2D@\3\2\2"+
+		"\2EH\3\2\2\2FD\3\2\2\2FG\3\2\2\2G\t\3\2\2\2HF\3\2\2\2IJ\5\f\7\2JS\b\6"+
+		"\1\2KL\7\6\2\2LM\5\f\7\2MN\b\6\1\2NT\3\2\2\2OP\7\7\2\2PQ\5\f\7\2QR\b\6"+
+		"\1\2RT\3\2\2\2SK\3\2\2\2SO\3\2\2\2ST\3\2\2\2T\13\3\2\2\2UV\5\16\b\2Va"+
+		"\b\7\1\2WX\7\b\2\2XY\5\16\b\2YZ\b\7\1\2Z`\3\2\2\2[\\\7\t\2\2\\]\5\16\b"+
+		"\2]^\b\7\1\2^`\3\2\2\2_W\3\2\2\2_[\3\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2\2"+
+		"\2b\r\3\2\2\2ca\3\2\2\2de\5\20\t\2et\b\b\1\2fg\7\n\2\2gh\5\20\t\2hi\b"+
+		"\b\1\2is\3\2\2\2jk\7\13\2\2kl\5\20\t\2lm\b\b\1\2ms\3\2\2\2no\7\f\2\2o"+
+		"p\5\20\t\2pq\b\b\1\2qs\3\2\2\2rf\3\2\2\2rj\3\2\2\2rn\3\2\2\2sv\3\2\2\2"+
+		"tr\3\2\2\2tu\3\2\2\2u\17\3\2\2\2vt\3\2\2\2wz\b\t\1\2xy\7\r\2\2y{\b\t\1"+
+		"\2zx\3\2\2\2z{\3\2\2\2{|\3\2\2\2|}\5\22\n\2}~\b\t\1\2~\21\3\2\2\2\177"+
+		"\u0080\5\24\13\2\u0080\u0087\b\n\1\2\u0081\u0082\7\16\2\2\u0082\u0083"+
+		"\5\24\13\2\u0083\u0084\b\n\1\2\u0084\u0086\3\2\2\2\u0085\u0081\3\2\2\2"+
+		"\u0086\u0089\3\2\2\2\u0087\u0085\3\2\2\2\u0087\u0088\3\2\2\2\u0088\23"+
+		"\3\2\2\2\u0089\u0087\3\2\2\2\u008a\u008b\5\26\f\2\u008b\u0091\b\13\1\2"+
+		"\u008c\u008d\7\17\2\2\u008d\u008e\7\63\2\2\u008e\u0090\b\13\1\2\u008f"+
+		"\u008c\3\2\2\2\u0090\u0093\3\2\2\2\u0091\u008f\3\2\2\2\u0091\u0092\3\2"+
+		"\2\2\u0092\25\3\2\2\2\u0093\u0091\3\2\2\2\u0094\u0095\7\63\2\2\u0095\u00d0"+
+		"\b\f\1\2\u0096\u0097\5\30\r\2\u0097\u0098\b\f\1\2\u0098\u00d0\3\2\2\2"+
+		"\u0099\u009a\5\32\16\2\u009a\u009b\b\f\1\2\u009b\u00d0\3\2\2\2\u009c\u009d"+
+		"\5\34\17\2\u009d\u009e\b\f\1\2\u009e\u00d0\3\2\2\2\u009f\u00a0\5\36\20"+
+		"\2\u00a0\u00a1\b\f\1\2\u00a1\u00d0\3\2\2\2\u00a2\u00a3\5 \21\2\u00a3\u00a4"+
+		"\b\f\1\2\u00a4\u00d0\3\2\2\2\u00a5\u00a6\7\20\2\2\u00a6\u00a7\7\21\2\2"+
+		"\u00a7\u00a8\7\63\2\2\u00a8\u00a9\7\22\2\2\u00a9\u00d0\b\f\1\2\u00aa\u00ab"+
+		"\7\23\2\2\u00ab\u00ac\7\21\2\2\u00ac\u00ad\5\4\3\2\u00ad\u00ae\7\24\2"+
+		"\2\u00ae\u00af\5\4\3\2\u00af\u00b0\7\24\2\2\u00b0\u00b1\5\4\3\2\u00b1"+
+		"\u00b2\7\24\2\2\u00b2\u00b3\5\4\3\2\u00b3\u00b4\7\22\2\2\u00b4\u00b5\b"+
+		"\f\1\2\u00b5\u00d0\3\2\2\2\u00b6\u00b7\7\25\2\2\u00b7\u00b8\7\21\2\2\u00b8"+
+		"\u00b9\7\65\2\2\u00b9\u00ba\7\22\2\2\u00ba\u00d0\b\f\1\2\u00bb\u00bc\7"+
+		"\26\2\2\u00bc\u00d0\b\f\1\2\u00bd\u00be\7\27\2\2\u00be\u00d0\b\f\1\2\u00bf"+
+		"\u00c0\7\65\2\2\u00c0\u00d0\b\f\1\2\u00c1\u00c2\7\66\2\2\u00c2\u00d0\b"+
+		"\f\1\2\u00c3\u00c4\7\30\2\2\u00c4\u00d0\b\f\1\2\u00c5\u00c6\7\64\2\2\u00c6"+
+		"\u00d0\b\f\1\2\u00c7\u00c8\5\"\22\2\u00c8\u00c9\b\f\1\2\u00c9\u00d0\3"+
+		"\2\2\2\u00ca\u00cb\7\21\2\2\u00cb\u00cc\5\26\f\2\u00cc\u00cd\7\22\2\2"+
+		"\u00cd\u00ce\b\f\1\2\u00ce\u00d0\3\2\2\2\u00cf\u0094\3\2\2\2\u00cf\u0096"+
+		"\3\2\2\2\u00cf\u0099\3\2\2\2\u00cf\u009c\3\2\2\2\u00cf\u009f\3\2\2\2\u00cf"+
+		"\u00a2\3\2\2\2\u00cf\u00a5\3\2\2\2\u00cf\u00aa\3\2\2\2\u00cf\u00b6\3\2"+
+		"\2\2\u00cf\u00bb\3\2\2\2\u00cf\u00bd\3\2\2\2\u00cf\u00bf\3\2\2\2\u00cf"+
+		"\u00c1\3\2\2\2\u00cf\u00c3\3\2\2\2\u00cf\u00c5\3\2\2\2\u00cf\u00c7\3\2"+
+		"\2\2\u00cf\u00ca\3\2\2\2\u00d0\27\3\2\2\2\u00d1\u00d2\7\31\2\2\u00d2\u00d6"+
+		"\b\r\1\2\u00d3\u00d4\7\32\2\2\u00d4\u00d5\7\63\2\2\u00d5\u00d7\b\r\1\2"+
+		"\u00d6\u00d3\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u00d8\3\2\2\2\u00d8\u00d9"+
+		"\7\63\2\2\u00d9\u00da\7\33\2\2\u00da\u00db\5\4\3\2\u00db\u00dc\b\r\1\2"+
+		"\u00dc\31\3\2\2\2\u00dd\u00de\7\34\2\2\u00de\u00df\5\4\3\2\u00df\u00e0"+
+		"\7\35\2\2\u00e0\u00e1\5\4\3\2\u00e1\u00e2\7\36\2\2\u00e2\u00e3\5\4\3\2"+
+		"\u00e3\u00e4\b\16\1\2\u00e4\33\3\2\2\2\u00e5\u00e6\7\37\2\2\u00e6\u00f6"+
+		"\b\17\1\2\u00e7\u00e8\7\63\2\2\u00e8\u00e9\7 \2\2\u00e9\u00ea\5\4\3\2"+
+		"\u00ea\u00f3\b\17\1\2\u00eb\u00ec\7!\2\2\u00ec\u00ed\7\63\2\2\u00ed\u00ee"+
+		"\7 \2\2\u00ee\u00ef\5\4\3\2\u00ef\u00f0\b\17\1\2\u00f0\u00f2\3\2\2\2\u00f1"+
+		"\u00eb\3\2\2\2\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2"+
+		"\2\2\u00f4\u00f7\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00e7\3\2\2\2\u00f6"+
+		"\u00f7\3\2\2\2\u00f7\u00f8\3\2\2\2\u00f8\u00f9\7\"\2\2\u00f9\35\3\2\2"+
+		"\2\u00fa\u00fb\7#\2\2\u00fb\u0107\b\20\1\2\u00fc\u00fd\5\4\3\2\u00fd\u0104"+
+		"\b\20\1\2\u00fe\u00ff\7!\2\2\u00ff\u0100\5\4\3\2\u0100\u0101\b\20\1\2"+
+		"\u0101\u0103\3\2\2\2\u0102\u00fe\3\2\2\2\u0103\u0106\3\2\2\2\u0104\u0102"+
+		"\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0108\3\2\2\2\u0106\u0104\3\2\2\2\u0107"+
+		"\u00fc\3\2\2\2\u0107\u0108\3\2\2\2\u0108\u0109\3\2\2\2\u0109\u010a\7$"+
+		"\2\2\u010a\37\3\2\2\2\u010b\u010c\7%\2\2\u010c\u010d\5\4\3\2\u010d\u010e"+
+		"\7&\2\2\u010e\u010f\7\'\2\2\u010f\u0110\7\33\2\2\u0110\u0111\5\4\3\2\u0111"+
+		"\u0112\7\36\2\2\u0112\u0113\7\33\2\2\u0113\u0114\5\4\3\2\u0114\u0115\b"+
+		"\21\1\2\u0115!\3\2\2\2\u0116\u016f\7\f\2\2\u0117\u0118\7(\2\2\u0118\u0119"+
+		"\7\21\2\2\u0119\u011a\5\4\3\2\u011a\u011b\7\24\2\2\u011b\u011c\5\4\3\2"+
+		"\u011c\u011d\7\22\2\2\u011d\u011e\b\22\1\2\u011e\u0170\3\2\2\2\u011f\u0120"+
+		"\7)\2\2\u0120\u0121\7\21\2\2\u0121\u0122\5\4\3\2\u0122\u0123\7\22\2\2"+
+		"\u0123\u0124\b\22\1\2\u0124\u0170\3\2\2\2\u0125\u0126\7*\2\2\u0126\u0127"+
+		"\7\21\2\2\u0127\u0128\5\4\3\2\u0128\u0129\7\24\2\2\u0129\u012a\5\4\3\2"+
+		"\u012a\u012b\7\22\2\2\u012b\u012c\b\22\1\2\u012c\u0170\3\2\2\2\u012d\u012e"+
+		"\7+\2\2\u012e\u012f\7\21\2\2\u012f\u0130\5\4\3\2\u0130\u0131\7\24\2\2"+
+		"\u0131\u0132\5\4\3\2\u0132\u0133\7\22\2\2\u0133\u0134\b\22\1\2\u0134\u0170"+
+		"\3\2\2\2\u0135\u0136\7,\2\2\u0136\u0137\7\21\2\2\u0137\u0138\5\4\3\2\u0138"+
+		"\u0139\7\24\2\2\u0139\u013a\5\4\3\2\u013a\u013b\7\24\2\2\u013b\u013c\5"+
+		"\4\3\2\u013c\u013d\7\22\2\2\u013d\u013e\b\22\1\2\u013e\u0170\3\2\2\2\u013f"+
+		"\u0140\7-\2\2\u0140\u0141\7\21\2\2\u0141\u0142\5\4\3\2\u0142\u0143\7\24"+
+		"\2\2\u0143\u0144\5\4\3\2\u0144\u0145\7\24\2\2\u0145\u0146\5\4\3\2\u0146"+
+		"\u0147\7\22\2\2\u0147\u0148\b\22\1\2\u0148\u0170\3\2\2\2\u0149\u014a\7"+
+		".\2\2\u014a\u014b\7\21\2\2\u014b\u014c\5\4\3\2\u014c\u014d\7\24\2\2\u014d"+
+		"\u014e\5\4\3\2\u014e\u014f\7\24\2\2\u014f\u0150\5\4\3\2\u0150\u0151\7"+
+		"\22\2\2\u0151\u0152\b\22\1\2\u0152\u0170\3\2\2\2\u0153\u0154\7/\2\2\u0154"+
+		"\u0155\7\21\2\2\u0155\u0156\5\4\3\2\u0156\u0157\7\24\2\2\u0157\u0158\5"+
+		"\4\3\2\u0158\u0159\7\24\2\2\u0159\u015a\5\4\3\2\u015a\u015b\7\22\2\2\u015b"+
+		"\u015c\b\22\1\2\u015c\u0170\3\2\2\2\u015d\u015e\7\63\2\2\u015e\u015f\7"+
+		"\21\2\2\u015f\u016b\b\22\1\2\u0160\u0161\5\4\3\2\u0161\u0168\b\22\1\2"+
+		"\u0162\u0163\7\24\2\2\u0163\u0164\5\4\3\2\u0164\u0165\b\22\1\2\u0165\u0167"+
+		"\3\2\2\2\u0166\u0162\3\2\2\2\u0167\u016a\3\2\2\2\u0168\u0166\3\2\2\2\u0168"+
+		"\u0169\3\2\2\2\u0169\u016c\3\2\2\2\u016a\u0168\3\2\2\2\u016b\u0160\3\2"+
+		"\2\2\u016b\u016c\3\2\2\2\u016c\u016d\3\2\2\2\u016d\u016e\7\22\2\2\u016e"+
+		"\u0170\b\22\1\2\u016f\u0117\3\2\2\2\u016f\u011f\3\2\2\2\u016f\u0125\3"+
+		"\2\2\2\u016f\u012d\3\2\2\2\u016f\u0135\3\2\2\2\u016f\u013f\3\2\2\2\u016f"+
+		"\u0149\3\2\2\2\u016f\u0153\3\2\2\2\u016f\u015d\3\2\2\2\u0170#\3\2\2\2"+
+		"\26\60;FS_artz\u0087\u0091\u00cf\u00d6\u00f3\u00f6\u0104\u0107\u0168\u016b"+
+		"\u016f";
+	public static final ATN _ATN =
+		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/qir/parser/test.qir b/src/qir/parser/test.qir
index e9487f5a18860be0d998ff851db7bdc8132e6198..e0e83d38fa75ee9aa3d9cd5fc06ec808f52c9d29 100644
--- a/src/qir/parser/test.qir
+++ b/src/qir/parser/test.qir
@@ -1 +1 @@
-(fun : { x:int ; y:list[string] } x -> x) @ [ { x = 2; y = 3 + 4 } : { x : int; y : int }; [ "toto" ] : list[string]; (fun : int -> (int -> int) -> int x -> x + 2) ]
+(fun x -> x) @ [ { x = 2; y = 3 + 4 }; [ "toto" ]; (fun x -> x + 2) ]