aboutsummaryrefslogtreecommitdiff
path: root/ql/test
diff options
context:
space:
mode:
Diffstat (limited to 'ql/test')
-rw-r--r--ql/test/__pycache__/test.cpython-35.pycbin0 -> 2759 bytes
-rw-r--r--ql/test/expression_evaluation/__pycache__/test_expression_evaluation.cpython-35.pycbin0 -> 2258 bytes
-rw-r--r--ql/test/expression_evaluation/test_expression_evaluation.py49
-rw-r--r--ql/test/expression_evaluation/valid/test001.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test002.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test003.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test004.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test005.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test006.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test007.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test008.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test009.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test010.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test011.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test012.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test013.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test014.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test015.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test016.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test017.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test018.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test019.ql5
-rw-r--r--ql/test/expression_evaluation/valid/test020.ql5
-rw-r--r--ql/test/lexing/__pycache__/test_lexing.cpython-35.pycbin0 -> 817 bytes
-rw-r--r--ql/test/lexing/invalid/test001.ql2
-rw-r--r--ql/test/lexing/invalid/test002.ql2
-rw-r--r--ql/test/lexing/invalid/test003.ql2
-rw-r--r--ql/test/lexing/invalid/test004.ql2
-rw-r--r--ql/test/lexing/invalid/test005.ql2
-rw-r--r--ql/test/lexing/invalid/test006.ql2
-rw-r--r--ql/test/lexing/invalid/test007.ql2
-rw-r--r--ql/test/lexing/invalid/test008.ql2
-rw-r--r--ql/test/lexing/invalid/test009.ql2
-rw-r--r--ql/test/lexing/invalid/test010.ql2
-rw-r--r--ql/test/lexing/invalid/test011.ql2
-rw-r--r--ql/test/lexing/invalid/test012.ql2
-rw-r--r--ql/test/lexing/invalid/test013.ql2
-rw-r--r--ql/test/lexing/invalid/test014.ql2
-rw-r--r--ql/test/lexing/invalid/test015.ql2
-rw-r--r--ql/test/lexing/invalid/test016.ql2
-rw-r--r--ql/test/lexing/invalid/test017.ql2
-rw-r--r--ql/test/lexing/invalid/test018.ql2
-rw-r--r--ql/test/lexing/invalid/test019.ql2
-rw-r--r--ql/test/lexing/test_lexing.py15
-rw-r--r--ql/test/lexing/valid/test001.ql2
-rw-r--r--ql/test/lexing/valid/test002.ql2
-rw-r--r--ql/test/lexing/valid/test003.ql2
-rw-r--r--ql/test/lexing/valid/test004.ql2
-rw-r--r--ql/test/lexing/valid/test005.ql2
-rw-r--r--ql/test/lexing/valid/test006.ql2
-rw-r--r--ql/test/lexing/valid/test007.ql2
-rw-r--r--ql/test/lexing/valid/test008.ql2
-rw-r--r--ql/test/lexing/valid/test009.ql2
-rw-r--r--ql/test/lexing/valid/test010.ql2
-rw-r--r--ql/test/lexing/valid/test011.ql2
-rw-r--r--ql/test/lexing/valid/test012.ql2
-rw-r--r--ql/test/lexing/valid/test013.ql2
-rw-r--r--ql/test/lexing/valid/test014.ql2
-rw-r--r--ql/test/lexing/valid/test015.ql2
-rw-r--r--ql/test/lexing/valid/test016.ql2
-rw-r--r--ql/test/lexing/valid/test017.ql2
-rw-r--r--ql/test/lexing/valid/test018.ql2
-rw-r--r--ql/test/lexing/valid/test019.ql2
-rw-r--r--ql/test/lexing/valid/test020.ql2
-rw-r--r--ql/test/lexing/valid/test021.ql2
-rw-r--r--ql/test/lexing/valid/test022.ql2
-rw-r--r--ql/test/lexing/valid/test023.ql2
-rw-r--r--ql/test/lexing/valid/test024.ql2
-rw-r--r--ql/test/lexing/valid/test025.ql2
-rw-r--r--ql/test/lexing/valid/test026.ql2
-rw-r--r--ql/test/lexing/valid/test027.ql2
-rw-r--r--ql/test/lexing/valid/test028.ql2
-rw-r--r--ql/test/lexing/valid/test029.ql2
-rw-r--r--ql/test/lexing/valid/test030.ql2
-rw-r--r--ql/test/lexing/valid/test031.ql2
-rw-r--r--ql/test/lexing/valid/test032.ql2
-rw-r--r--ql/test/lexing/valid/test033.ql2
-rw-r--r--ql/test/lexing/valid/test034.ql2
-rw-r--r--ql/test/lexing/valid/test035.ql2
-rw-r--r--ql/test/lexing/valid/test036.ql2
-rw-r--r--ql/test/lexing/valid/test037.ql2
-rw-r--r--ql/test/lexing/valid/test038.ql2
-rw-r--r--ql/test/lexing/valid/test039.ql2
-rw-r--r--ql/test/lexing/valid/test040.ql2
-rw-r--r--ql/test/lexing/valid/test041.ql2
-rw-r--r--ql/test/lexing/valid/test042.ql2
-rw-r--r--ql/test/lexing/valid/test043.ql2
-rw-r--r--ql/test/lexing/valid/test044.ql2
-rw-r--r--ql/test/lexing/valid/test045.ql2
-rw-r--r--ql/test/parsing/__pycache__/test_parsing.cpython-35.pycbin0 -> 881 bytes
-rw-r--r--ql/test/parsing/invalid/test001.ql1
-rw-r--r--ql/test/parsing/invalid/test002.ql3
-rw-r--r--ql/test/parsing/invalid/test003.ql3
-rw-r--r--ql/test/parsing/invalid/test004.ql5
-rw-r--r--ql/test/parsing/invalid/test005.ql5
-rw-r--r--ql/test/parsing/invalid/test006.ql5
-rw-r--r--ql/test/parsing/invalid/test007.ql5
-rw-r--r--ql/test/parsing/invalid/test018.ql7
-rw-r--r--ql/test/parsing/invalid/test019.ql5
-rw-r--r--ql/test/parsing/test_parsing.py16
-rw-r--r--ql/test/parsing/valid/test001.ql5
-rw-r--r--ql/test/parsing/valid/test002.ql5
-rw-r--r--ql/test/parsing/valid/test003.ql5
-rw-r--r--ql/test/parsing/valid/test004.ql5
-rw-r--r--ql/test/parsing/valid/test005.ql5
-rw-r--r--ql/test/parsing/valid/test006.ql5
-rw-r--r--ql/test/parsing/valid/test007.ql8
-rw-r--r--ql/test/parsing/valid/test008.ql8
-rw-r--r--ql/test/parsing/valid/test009.ql20
-rw-r--r--ql/test/parsing/valid/test010.ql5
-rw-r--r--ql/test/parsing/valid/test011.ql5
-rw-r--r--ql/test/parsing/valid/test012.ql5
-rw-r--r--ql/test/semantic_analysis/__pycache__/test_semantic_analysis.cpython-35.pycbin0 -> 1778 bytes
-rw-r--r--ql/test/semantic_analysis/invalid/test001.ql9
-rw-r--r--ql/test/semantic_analysis/invalid/test002.ql9
-rw-r--r--ql/test/semantic_analysis/invalid/test003.ql13
-rw-r--r--ql/test/semantic_analysis/invalid/test004.ql11
-rw-r--r--ql/test/semantic_analysis/invalid/test005.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test006.ql7
-rw-r--r--ql/test/semantic_analysis/invalid/test007.ql9
-rw-r--r--ql/test/semantic_analysis/invalid/test008.ql7
-rw-r--r--ql/test/semantic_analysis/invalid/test009.ql7
-rw-r--r--ql/test/semantic_analysis/invalid/test010.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test011.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test012.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test013.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test014.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test015.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test016.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test017.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test018.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test019.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test020.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test021.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test022.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test023.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test024.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test025.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test026.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test027.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test028.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test029.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test030.ql7
-rw-r--r--ql/test/semantic_analysis/invalid/test031.ql5
-rw-r--r--ql/test/semantic_analysis/invalid/test032.ql5
-rw-r--r--ql/test/semantic_analysis/test_semantic_analysis.py39
-rw-r--r--ql/test/semantic_analysis/valid/test001.ql9
-rw-r--r--ql/test/semantic_analysis/valid/test002.ql7
-rw-r--r--ql/test/semantic_analysis/valid/test003.ql9
-rw-r--r--ql/test/semantic_analysis/valid/test004.ql7
-rw-r--r--ql/test/semantic_analysis/valid/test005.ql15
-rw-r--r--ql/test/semantic_analysis/valid/test006.ql13
-rw-r--r--ql/test/semantic_analysis/valid/test007.ql9
-rw-r--r--ql/test/semantic_analysis/valid/test008.ql9
-rw-r--r--ql/test/semantic_analysis/valid/test009.ql7
-rw-r--r--ql/test/semantic_analysis/valid/test010.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test011.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test012.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test013.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test014.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test015.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test016.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test017.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test018.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test019.ql5
-rw-r--r--ql/test/semantic_analysis/valid/test020.ql7
-rw-r--r--ql/test/semantic_analysis/valid/test021.ql5
-rw-r--r--ql/test/test.py80
168 files changed, 888 insertions, 0 deletions
diff --git a/ql/test/__pycache__/test.cpython-35.pyc b/ql/test/__pycache__/test.cpython-35.pyc
new file mode 100644
index 0000000..2eb18b1
--- /dev/null
+++ b/ql/test/__pycache__/test.cpython-35.pyc
Binary files differ
diff --git a/ql/test/expression_evaluation/__pycache__/test_expression_evaluation.cpython-35.pyc b/ql/test/expression_evaluation/__pycache__/test_expression_evaluation.cpython-35.pyc
new file mode 100644
index 0000000..2104122
--- /dev/null
+++ b/ql/test/expression_evaluation/__pycache__/test_expression_evaluation.cpython-35.pyc
Binary files differ
diff --git a/ql/test/expression_evaluation/test_expression_evaluation.py b/ql/test/expression_evaluation/test_expression_evaluation.py
new file mode 100644
index 0000000..067ebda
--- /dev/null
+++ b/ql/test/expression_evaluation/test_expression_evaluation.py
@@ -0,0 +1,49 @@
+from json import loads
+
+from ql.ast.extractors.extractor import extract_gui_model
+from ql.ast.extractors.extractor import extract_identifier_types
+from ql.ast.visitors.expression_evaluator import ExpressionEvaluator
+from ql.ast.visitors.type_visitor import TypeVisitor
+from ql.types.boolean import QLBoolean
+from ql.types.date import QLDate
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.string import QLString
+from ql.test.test import Test
+
+
+class TestExpressionEvaluation(Test):
+ def __init__(self, directory, lexer, parser):
+ super(TestExpressionEvaluation, self).__init__('expression evaluation', directory)
+ self.__lexer = lexer
+ self.__parser = parser
+
+ def test_file(self, file):
+ ast = self.__parser.parse(file, self.__lexer.lexer)
+
+ if not self.__parser.errors:
+ TypeVisitor(extract_identifier_types(ast)).visit(ast)
+ model = extract_gui_model(ast)
+ result_type, result_value = file.split('\n')[0].split()[-2:]
+ correct_result = None
+
+ if result_type == 'QLBoolean' and result_value == 'True':
+ correct_result = QLBoolean(True)
+ elif result_type == 'QLBoolean':
+ correct_result = QLBoolean()
+ elif result_type == 'QLDate':
+ day, month, year = loads(result_value)
+ correct_result = QLDate(day, month, year)
+ elif result_type == 'QLDecimal':
+ correct_result = QLDecimal(result_value)
+ elif result_type == 'QLInteger':
+ correct_result = QLInteger(result_value)
+ elif result_type == 'QLMoney':
+ correct_result = QLMoney(result_value)
+ elif result_type == 'QLString':
+ correct_result = QLString(result_value)
+
+ expression_evaluator = ExpressionEvaluator(model)
+ expression_evaluator.visit(ast.block[0].answer)
+ return bool(expression_evaluator.result == correct_result)
diff --git a/ql/test/expression_evaluation/valid/test001.ql b/ql/test/expression_evaluation/valid/test001.ql
new file mode 100644
index 0000000..fc72525
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test001.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test002.ql b/ql/test/expression_evaluation/valid/test002.ql
new file mode 100644
index 0000000..f4d722b
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test002.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test003.ql b/ql/test/expression_evaluation/valid/test003.ql
new file mode 100644
index 0000000..2998f36
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test003.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = not False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test004.ql b/ql/test/expression_evaluation/valid/test004.ql
new file mode 100644
index 0000000..fcfd827
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test004.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = not True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test005.ql b/ql/test/expression_evaluation/valid/test005.ql
new file mode 100644
index 0000000..0ee8989
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test005.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = False == False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test006.ql b/ql/test/expression_evaluation/valid/test006.ql
new file mode 100644
index 0000000..70f15f2
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test006.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = False == True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test007.ql b/ql/test/expression_evaluation/valid/test007.ql
new file mode 100644
index 0000000..76f37b0
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test007.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = True == False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test008.ql b/ql/test/expression_evaluation/valid/test008.ql
new file mode 100644
index 0000000..f6d5710
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test008.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = True == True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test009.ql b/ql/test/expression_evaluation/valid/test009.ql
new file mode 100644
index 0000000..6a3d465
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test009.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = False != False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test010.ql b/ql/test/expression_evaluation/valid/test010.ql
new file mode 100644
index 0000000..e398dde
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test010.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = False != True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test011.ql b/ql/test/expression_evaluation/valid/test011.ql
new file mode 100644
index 0000000..3a7cbd1
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test011.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = True != False
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test012.ql b/ql/test/expression_evaluation/valid/test012.ql
new file mode 100644
index 0000000..2a7185e
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test012.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = True != True
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test013.ql b/ql/test/expression_evaluation/valid/test013.ql
new file mode 100644
index 0000000..bed71a2
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test013.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLDate [1,1,2018]
+form label {
+ "Question"
+ id : boolean = date(1,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test014.ql b/ql/test/expression_evaluation/valid/test014.ql
new file mode 100644
index 0000000..4d4413d
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test014.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean True
+form label {
+ "Question"
+ id : boolean = date(1,1,2018) == date(1,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test015.ql b/ql/test/expression_evaluation/valid/test015.ql
new file mode 100644
index 0000000..06a75ba
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test015.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(1,1,2018) == date(1,1,2017)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test016.ql b/ql/test/expression_evaluation/valid/test016.ql
new file mode 100644
index 0000000..3cb4215
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test016.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(1,1,109) == date(1,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test017.ql b/ql/test/expression_evaluation/valid/test017.ql
new file mode 100644
index 0000000..d4a3bbf
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test017.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(1,1,2018) == date(1,7,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test018.ql b/ql/test/expression_evaluation/valid/test018.ql
new file mode 100644
index 0000000..38f80ea
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test018.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(1,3,2018) == date(1,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test019.ql b/ql/test/expression_evaluation/valid/test019.ql
new file mode 100644
index 0000000..8d797b5
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test019.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(1,1,2018) == date(5,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/expression_evaluation/valid/test020.ql b/ql/test/expression_evaluation/valid/test020.ql
new file mode 100644
index 0000000..5d401cf
--- /dev/null
+++ b/ql/test/expression_evaluation/valid/test020.ql
@@ -0,0 +1,5 @@
+// Correct result type and result value: QLBoolean False
+form label {
+ "Question"
+ id : boolean = date(21,1,2018) == date(1,1,2018)
+} \ No newline at end of file
diff --git a/ql/test/lexing/__pycache__/test_lexing.cpython-35.pyc b/ql/test/lexing/__pycache__/test_lexing.cpython-35.pyc
new file mode 100644
index 0000000..eca2f01
--- /dev/null
+++ b/ql/test/lexing/__pycache__/test_lexing.cpython-35.pyc
Binary files differ
diff --git a/ql/test/lexing/invalid/test001.ql b/ql/test/lexing/invalid/test001.ql
new file mode 100644
index 0000000..37bf0fd
--- /dev/null
+++ b/ql/test/lexing/invalid/test001.ql
@@ -0,0 +1,2 @@
+// Illegal character (`)
+` \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test002.ql b/ql/test/lexing/invalid/test002.ql
new file mode 100644
index 0000000..b691de9
--- /dev/null
+++ b/ql/test/lexing/invalid/test002.ql
@@ -0,0 +1,2 @@
+// Illegal character (~)
+~ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test003.ql b/ql/test/lexing/invalid/test003.ql
new file mode 100644
index 0000000..b75fc41
--- /dev/null
+++ b/ql/test/lexing/invalid/test003.ql
@@ -0,0 +1,2 @@
+// Illegal character (@)
+@ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test004.ql b/ql/test/lexing/invalid/test004.ql
new file mode 100644
index 0000000..9b3e1f7
--- /dev/null
+++ b/ql/test/lexing/invalid/test004.ql
@@ -0,0 +1,2 @@
+// Illegal character (#)
+# \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test005.ql b/ql/test/lexing/invalid/test005.ql
new file mode 100644
index 0000000..9bd5fc4
--- /dev/null
+++ b/ql/test/lexing/invalid/test005.ql
@@ -0,0 +1,2 @@
+// Illegal character (€)
+€ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test006.ql b/ql/test/lexing/invalid/test006.ql
new file mode 100644
index 0000000..a7c1336
--- /dev/null
+++ b/ql/test/lexing/invalid/test006.ql
@@ -0,0 +1,2 @@
+// Illegal character (%)
+% \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test007.ql b/ql/test/lexing/invalid/test007.ql
new file mode 100644
index 0000000..39cbd63
--- /dev/null
+++ b/ql/test/lexing/invalid/test007.ql
@@ -0,0 +1,2 @@
+// Illegal character (^)
+^ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test008.ql b/ql/test/lexing/invalid/test008.ql
new file mode 100644
index 0000000..82f2836
--- /dev/null
+++ b/ql/test/lexing/invalid/test008.ql
@@ -0,0 +1,2 @@
+// Illegal character (&)
+& \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test009.ql b/ql/test/lexing/invalid/test009.ql
new file mode 100644
index 0000000..e92526e
--- /dev/null
+++ b/ql/test/lexing/invalid/test009.ql
@@ -0,0 +1,2 @@
+// Illegal character (_)
+_ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test010.ql b/ql/test/lexing/invalid/test010.ql
new file mode 100644
index 0000000..30c8837
--- /dev/null
+++ b/ql/test/lexing/invalid/test010.ql
@@ -0,0 +1,2 @@
+// Illegal character ([)
+[ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test011.ql b/ql/test/lexing/invalid/test011.ql
new file mode 100644
index 0000000..f047fbc
--- /dev/null
+++ b/ql/test/lexing/invalid/test011.ql
@@ -0,0 +1,2 @@
+// Illegal character (])
+] \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test012.ql b/ql/test/lexing/invalid/test012.ql
new file mode 100644
index 0000000..81e3796
--- /dev/null
+++ b/ql/test/lexing/invalid/test012.ql
@@ -0,0 +1,2 @@
+// Illegal character (\)
+\ \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test013.ql b/ql/test/lexing/invalid/test013.ql
new file mode 100644
index 0000000..0a6d02c
--- /dev/null
+++ b/ql/test/lexing/invalid/test013.ql
@@ -0,0 +1,2 @@
+// Illegal character (|)
+| \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test014.ql b/ql/test/lexing/invalid/test014.ql
new file mode 100644
index 0000000..48ede2c
--- /dev/null
+++ b/ql/test/lexing/invalid/test014.ql
@@ -0,0 +1,2 @@
+// Illegal character (;)
+; \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test015.ql b/ql/test/lexing/invalid/test015.ql
new file mode 100644
index 0000000..ec798a0
--- /dev/null
+++ b/ql/test/lexing/invalid/test015.ql
@@ -0,0 +1,2 @@
+// Illegal character (')
+' \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test016.ql b/ql/test/lexing/invalid/test016.ql
new file mode 100644
index 0000000..6d67365
--- /dev/null
+++ b/ql/test/lexing/invalid/test016.ql
@@ -0,0 +1,2 @@
+// Illegal character (")
+" \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test017.ql b/ql/test/lexing/invalid/test017.ql
new file mode 100644
index 0000000..d8907bd
--- /dev/null
+++ b/ql/test/lexing/invalid/test017.ql
@@ -0,0 +1,2 @@
+// Illegal character (,)
+, \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test018.ql b/ql/test/lexing/invalid/test018.ql
new file mode 100644
index 0000000..73fece7
--- /dev/null
+++ b/ql/test/lexing/invalid/test018.ql
@@ -0,0 +1,2 @@
+// Illegal character (?)
+? \ No newline at end of file
diff --git a/ql/test/lexing/invalid/test019.ql b/ql/test/lexing/invalid/test019.ql
new file mode 100644
index 0000000..407e52e
--- /dev/null
+++ b/ql/test/lexing/invalid/test019.ql
@@ -0,0 +1,2 @@
+// Illegal characters (uppercase characters)
+A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \ No newline at end of file
diff --git a/ql/test/lexing/test_lexing.py b/ql/test/lexing/test_lexing.py
new file mode 100644
index 0000000..978b1d7
--- /dev/null
+++ b/ql/test/lexing/test_lexing.py
@@ -0,0 +1,15 @@
+from ql.test.test import Test
+
+
+class TestLexing(Test):
+ def __init__(self, directory, lexer):
+ super(TestLexing, self).__init__('lexing', directory)
+ self.__lexer = lexer
+
+ def test_file(self, file):
+ self.__lexer.tokenize(file)
+
+ if self.__lexer.errors:
+ return False
+
+ return True
diff --git a/ql/test/lexing/valid/test001.ql b/ql/test/lexing/valid/test001.ql
new file mode 100644
index 0000000..9862fb0
--- /dev/null
+++ b/ql/test/lexing/valid/test001.ql
@@ -0,0 +1,2 @@
+// Form token
+form \ No newline at end of file
diff --git a/ql/test/lexing/valid/test002.ql b/ql/test/lexing/valid/test002.ql
new file mode 100644
index 0000000..2efece0
--- /dev/null
+++ b/ql/test/lexing/valid/test002.ql
@@ -0,0 +1,2 @@
+// If token
+if \ No newline at end of file
diff --git a/ql/test/lexing/valid/test003.ql b/ql/test/lexing/valid/test003.ql
new file mode 100644
index 0000000..dc30033
--- /dev/null
+++ b/ql/test/lexing/valid/test003.ql
@@ -0,0 +1,2 @@
+// Boolean type token
+boolean \ No newline at end of file
diff --git a/ql/test/lexing/valid/test004.ql b/ql/test/lexing/valid/test004.ql
new file mode 100644
index 0000000..233e652
--- /dev/null
+++ b/ql/test/lexing/valid/test004.ql
@@ -0,0 +1,2 @@
+// Date type token
+date \ No newline at end of file
diff --git a/ql/test/lexing/valid/test005.ql b/ql/test/lexing/valid/test005.ql
new file mode 100644
index 0000000..9d1f615
--- /dev/null
+++ b/ql/test/lexing/valid/test005.ql
@@ -0,0 +1,2 @@
+// Decimal type token
+decimal \ No newline at end of file
diff --git a/ql/test/lexing/valid/test006.ql b/ql/test/lexing/valid/test006.ql
new file mode 100644
index 0000000..506c72e
--- /dev/null
+++ b/ql/test/lexing/valid/test006.ql
@@ -0,0 +1,2 @@
+// Integer type token
+integer \ No newline at end of file
diff --git a/ql/test/lexing/valid/test007.ql b/ql/test/lexing/valid/test007.ql
new file mode 100644
index 0000000..66c665f
--- /dev/null
+++ b/ql/test/lexing/valid/test007.ql
@@ -0,0 +1,2 @@
+// Money type token
+money \ No newline at end of file
diff --git a/ql/test/lexing/valid/test008.ql b/ql/test/lexing/valid/test008.ql
new file mode 100644
index 0000000..3455595
--- /dev/null
+++ b/ql/test/lexing/valid/test008.ql
@@ -0,0 +1,2 @@
+// String type token
+string \ No newline at end of file
diff --git a/ql/test/lexing/valid/test009.ql b/ql/test/lexing/valid/test009.ql
new file mode 100644
index 0000000..123a526
--- /dev/null
+++ b/ql/test/lexing/valid/test009.ql
@@ -0,0 +1,2 @@
+// Plus token
++ \ No newline at end of file
diff --git a/ql/test/lexing/valid/test010.ql b/ql/test/lexing/valid/test010.ql
new file mode 100644
index 0000000..ac494f7
--- /dev/null
+++ b/ql/test/lexing/valid/test010.ql
@@ -0,0 +1,2 @@
+// Minus token
+- \ No newline at end of file
diff --git a/ql/test/lexing/valid/test011.ql b/ql/test/lexing/valid/test011.ql
new file mode 100644
index 0000000..c53f248
--- /dev/null
+++ b/ql/test/lexing/valid/test011.ql
@@ -0,0 +1,2 @@
+// Times token
+* \ No newline at end of file
diff --git a/ql/test/lexing/valid/test012.ql b/ql/test/lexing/valid/test012.ql
new file mode 100644
index 0000000..195d9b9
--- /dev/null
+++ b/ql/test/lexing/valid/test012.ql
@@ -0,0 +1,2 @@
+// Divide token
+/ \ No newline at end of file
diff --git a/ql/test/lexing/valid/test013.ql b/ql/test/lexing/valid/test013.ql
new file mode 100644
index 0000000..d1c0471
--- /dev/null
+++ b/ql/test/lexing/valid/test013.ql
@@ -0,0 +1,2 @@
+// Colon token
+: \ No newline at end of file
diff --git a/ql/test/lexing/valid/test014.ql b/ql/test/lexing/valid/test014.ql
new file mode 100644
index 0000000..f72179a
--- /dev/null
+++ b/ql/test/lexing/valid/test014.ql
@@ -0,0 +1,2 @@
+// Assign token
+= \ No newline at end of file
diff --git a/ql/test/lexing/valid/test015.ql b/ql/test/lexing/valid/test015.ql
new file mode 100644
index 0000000..09f1ea1
--- /dev/null
+++ b/ql/test/lexing/valid/test015.ql
@@ -0,0 +1,2 @@
+// Equals token
+== \ No newline at end of file
diff --git a/ql/test/lexing/valid/test016.ql b/ql/test/lexing/valid/test016.ql
new file mode 100644
index 0000000..9cc8e9b
--- /dev/null
+++ b/ql/test/lexing/valid/test016.ql
@@ -0,0 +1,2 @@
+// Not equals token
+!= \ No newline at end of file
diff --git a/ql/test/lexing/valid/test017.ql b/ql/test/lexing/valid/test017.ql
new file mode 100644
index 0000000..ce8af09
--- /dev/null
+++ b/ql/test/lexing/valid/test017.ql
@@ -0,0 +1,2 @@
+// Greater than token
+> \ No newline at end of file
diff --git a/ql/test/lexing/valid/test018.ql b/ql/test/lexing/valid/test018.ql
new file mode 100644
index 0000000..dad4f9c
--- /dev/null
+++ b/ql/test/lexing/valid/test018.ql
@@ -0,0 +1,2 @@
+// Greater equals token
+>= \ No newline at end of file
diff --git a/ql/test/lexing/valid/test019.ql b/ql/test/lexing/valid/test019.ql
new file mode 100644
index 0000000..39ec8a3
--- /dev/null
+++ b/ql/test/lexing/valid/test019.ql
@@ -0,0 +1,2 @@
+// Less than token
+< \ No newline at end of file
diff --git a/ql/test/lexing/valid/test020.ql b/ql/test/lexing/valid/test020.ql
new file mode 100644
index 0000000..902ec15
--- /dev/null
+++ b/ql/test/lexing/valid/test020.ql
@@ -0,0 +1,2 @@
+// Less equals token
+<= \ No newline at end of file
diff --git a/ql/test/lexing/valid/test021.ql b/ql/test/lexing/valid/test021.ql
new file mode 100644
index 0000000..296f504
--- /dev/null
+++ b/ql/test/lexing/valid/test021.ql
@@ -0,0 +1,2 @@
+// Not token
+not \ No newline at end of file
diff --git a/ql/test/lexing/valid/test022.ql b/ql/test/lexing/valid/test022.ql
new file mode 100644
index 0000000..1d4fe36
--- /dev/null
+++ b/ql/test/lexing/valid/test022.ql
@@ -0,0 +1,2 @@
+// Brace tokens
+{} \ No newline at end of file
diff --git a/ql/test/lexing/valid/test023.ql b/ql/test/lexing/valid/test023.ql
new file mode 100644
index 0000000..3b27a60
--- /dev/null
+++ b/ql/test/lexing/valid/test023.ql
@@ -0,0 +1,2 @@
+// Bracket tokens
+() \ No newline at end of file
diff --git a/ql/test/lexing/valid/test024.ql b/ql/test/lexing/valid/test024.ql
new file mode 100644
index 0000000..72854c9
--- /dev/null
+++ b/ql/test/lexing/valid/test024.ql
@@ -0,0 +1,2 @@
+// Whitespace tokens
+
diff --git a/ql/test/lexing/valid/test025.ql b/ql/test/lexing/valid/test025.ql
new file mode 100644
index 0000000..ceb93d0
--- /dev/null
+++ b/ql/test/lexing/valid/test025.ql
@@ -0,0 +1,2 @@
+// Identifier token (lowercase)
+testidentifier \ No newline at end of file
diff --git a/ql/test/lexing/valid/test026.ql b/ql/test/lexing/valid/test026.ql
new file mode 100644
index 0000000..90589b2
--- /dev/null
+++ b/ql/test/lexing/valid/test026.ql
@@ -0,0 +1,2 @@
+// Identifier token (camelcase)
+testIdentifier \ No newline at end of file
diff --git a/ql/test/lexing/valid/test027.ql b/ql/test/lexing/valid/test027.ql
new file mode 100644
index 0000000..076f4b0
--- /dev/null
+++ b/ql/test/lexing/valid/test027.ql
@@ -0,0 +1,2 @@
+// Identifier token (underscore)
+test_identifier \ No newline at end of file
diff --git a/ql/test/lexing/valid/test028.ql b/ql/test/lexing/valid/test028.ql
new file mode 100644
index 0000000..855dd9a
--- /dev/null
+++ b/ql/test/lexing/valid/test028.ql
@@ -0,0 +1,2 @@
+// Identifier token (number)
+identifier123 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test029.ql b/ql/test/lexing/valid/test029.ql
new file mode 100644
index 0000000..1d37fa2
--- /dev/null
+++ b/ql/test/lexing/valid/test029.ql
@@ -0,0 +1,2 @@
+// Boolean literal token (false)
+False \ No newline at end of file
diff --git a/ql/test/lexing/valid/test030.ql b/ql/test/lexing/valid/test030.ql
new file mode 100644
index 0000000..bc70591
--- /dev/null
+++ b/ql/test/lexing/valid/test030.ql
@@ -0,0 +1,2 @@
+// Boolean literal token (true)
+True \ No newline at end of file
diff --git a/ql/test/lexing/valid/test031.ql b/ql/test/lexing/valid/test031.ql
new file mode 100644
index 0000000..106a0ad
--- /dev/null
+++ b/ql/test/lexing/valid/test031.ql
@@ -0,0 +1,2 @@
+// Date literal token
+date(1, 1, 2018) \ No newline at end of file
diff --git a/ql/test/lexing/valid/test032.ql b/ql/test/lexing/valid/test032.ql
new file mode 100644
index 0000000..51cc57a
--- /dev/null
+++ b/ql/test/lexing/valid/test032.ql
@@ -0,0 +1,2 @@
+// Date literal token
+date(99, 99, 9999) \ No newline at end of file
diff --git a/ql/test/lexing/valid/test033.ql b/ql/test/lexing/valid/test033.ql
new file mode 100644
index 0000000..f6a8535
--- /dev/null
+++ b/ql/test/lexing/valid/test033.ql
@@ -0,0 +1,2 @@
+// Decimal literal token
+0.0 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test034.ql b/ql/test/lexing/valid/test034.ql
new file mode 100644
index 0000000..15b2e6a
--- /dev/null
+++ b/ql/test/lexing/valid/test034.ql
@@ -0,0 +1,2 @@
+// Decimal literal token
+3.14 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test035.ql b/ql/test/lexing/valid/test035.ql
new file mode 100644
index 0000000..49616a7
--- /dev/null
+++ b/ql/test/lexing/valid/test035.ql
@@ -0,0 +1,2 @@
+// Decimal literal token
+1234567890.0987654321 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test036.ql b/ql/test/lexing/valid/test036.ql
new file mode 100644
index 0000000..86f7a4e
--- /dev/null
+++ b/ql/test/lexing/valid/test036.ql
@@ -0,0 +1,2 @@
+// Decimal literal token
+999999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test037.ql b/ql/test/lexing/valid/test037.ql
new file mode 100644
index 0000000..174d0ce
--- /dev/null
+++ b/ql/test/lexing/valid/test037.ql
@@ -0,0 +1,2 @@
+// Integer literal token
+0 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test038.ql b/ql/test/lexing/valid/test038.ql
new file mode 100644
index 0000000..6740489
--- /dev/null
+++ b/ql/test/lexing/valid/test038.ql
@@ -0,0 +1,2 @@
+// Integer literal token
+1234567890 \ No newline at end of file
diff --git a/ql/test/lexing/valid/test039.ql b/ql/test/lexing/valid/test039.ql
new file mode 100644
index 0000000..d2dbc53
--- /dev/null
+++ b/ql/test/lexing/valid/test039.ql
@@ -0,0 +1,2 @@
+// String literal token
+"abcdefghijklmnopqrstuvwxyz" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test040.ql b/ql/test/lexing/valid/test040.ql
new file mode 100644
index 0000000..306582b
--- /dev/null
+++ b/ql/test/lexing/valid/test040.ql
@@ -0,0 +1,2 @@
+// String literal token
+"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test041.ql b/ql/test/lexing/valid/test041.ql
new file mode 100644
index 0000000..84f0aff
--- /dev/null
+++ b/ql/test/lexing/valid/test041.ql
@@ -0,0 +1,2 @@
+// String literal token
+"1234567890" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test042.ql b/ql/test/lexing/valid/test042.ql
new file mode 100644
index 0000000..d389d9f
--- /dev/null
+++ b/ql/test/lexing/valid/test042.ql
@@ -0,0 +1,2 @@
+// String literal token
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test043.ql b/ql/test/lexing/valid/test043.ql
new file mode 100644
index 0000000..6698694
--- /dev/null
+++ b/ql/test/lexing/valid/test043.ql
@@ -0,0 +1,2 @@
+// String literal token
+"`~!@#$%*()-=_+[]\{}|;:,./<>?" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test044.ql b/ql/test/lexing/valid/test044.ql
new file mode 100644
index 0000000..d09b55d
--- /dev/null
+++ b/ql/test/lexing/valid/test044.ql
@@ -0,0 +1,2 @@
+// String literal token
+"\'" \ No newline at end of file
diff --git a/ql/test/lexing/valid/test045.ql b/ql/test/lexing/valid/test045.ql
new file mode 100644
index 0000000..d85d414
--- /dev/null
+++ b/ql/test/lexing/valid/test045.ql
@@ -0,0 +1,2 @@
+// String literal token
+"\"" \ No newline at end of file
diff --git a/ql/test/parsing/__pycache__/test_parsing.cpython-35.pyc b/ql/test/parsing/__pycache__/test_parsing.cpython-35.pyc
new file mode 100644
index 0000000..4e89c3e
--- /dev/null
+++ b/ql/test/parsing/__pycache__/test_parsing.cpython-35.pyc
Binary files differ
diff --git a/ql/test/parsing/invalid/test001.ql b/ql/test/parsing/invalid/test001.ql
new file mode 100644
index 0000000..fab17ac
--- /dev/null
+++ b/ql/test/parsing/invalid/test001.ql
@@ -0,0 +1 @@
+// Empty file
diff --git a/ql/test/parsing/invalid/test002.ql b/ql/test/parsing/invalid/test002.ql
new file mode 100644
index 0000000..d84f901
--- /dev/null
+++ b/ql/test/parsing/invalid/test002.ql
@@ -0,0 +1,3 @@
+// Empty form without label
+form {
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test003.ql b/ql/test/parsing/invalid/test003.ql
new file mode 100644
index 0000000..57975a1
--- /dev/null
+++ b/ql/test/parsing/invalid/test003.ql
@@ -0,0 +1,3 @@
+// Empty form
+form testForm {
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test004.ql b/ql/test/parsing/invalid/test004.ql
new file mode 100644
index 0000000..6f2fb9f
--- /dev/null
+++ b/ql/test/parsing/invalid/test004.ql
@@ -0,0 +1,5 @@
+// Form without label
+form {
+ "Question?"
+ var : boolean
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test005.ql b/ql/test/parsing/invalid/test005.ql
new file mode 100644
index 0000000..5b67d6e
--- /dev/null
+++ b/ql/test/parsing/invalid/test005.ql
@@ -0,0 +1,5 @@
+// Question label without quotation marks
+form testForm {
+ question
+ var : cows
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test006.ql b/ql/test/parsing/invalid/test006.ql
new file mode 100644
index 0000000..b902dc9
--- /dev/null
+++ b/ql/test/parsing/invalid/test006.ql
@@ -0,0 +1,5 @@
+// Question with invalid type
+form testForm {
+ "Question?"
+ var : cows
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test007.ql b/ql/test/parsing/invalid/test007.ql
new file mode 100644
index 0000000..e16685e
--- /dev/null
+++ b/ql/test/parsing/invalid/test007.ql
@@ -0,0 +1,5 @@
+// Question identifier with quotation marks
+form testForm {
+ "Question?"
+ "var" : boolean
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test018.ql b/ql/test/parsing/invalid/test018.ql
new file mode 100644
index 0000000..80deece
--- /dev/null
+++ b/ql/test/parsing/invalid/test018.ql
@@ -0,0 +1,7 @@
+// Empty if conditional
+form testForm {
+ if () {
+ "Question?"
+ id : boolean
+ }
+} \ No newline at end of file
diff --git a/ql/test/parsing/invalid/test019.ql b/ql/test/parsing/invalid/test019.ql
new file mode 100644
index 0000000..1bde8f1
--- /dev/null
+++ b/ql/test/parsing/invalid/test019.ql
@@ -0,0 +1,5 @@
+// Empty if block
+form label {
+ if (1 == 2) {
+ }
+} \ No newline at end of file
diff --git a/ql/test/parsing/test_parsing.py b/ql/test/parsing/test_parsing.py
new file mode 100644
index 0000000..86900f9
--- /dev/null
+++ b/ql/test/parsing/test_parsing.py
@@ -0,0 +1,16 @@
+from ql.test.test import Test
+
+
+class TestParsing(Test):
+ def __init__(self, directory, lexer, parser):
+ super(TestParsing, self).__init__('parsing', directory)
+ self.__lexer = lexer
+ self.__parser = parser
+
+ def test_file(self, file):
+ self.__parser.parse(file, self.__lexer.lexer)
+
+ if self.__parser.errors:
+ return False
+
+ return True
diff --git a/ql/test/parsing/valid/test001.ql b/ql/test/parsing/valid/test001.ql
new file mode 100644
index 0000000..aecb488
--- /dev/null
+++ b/ql/test/parsing/valid/test001.ql
@@ -0,0 +1,5 @@
+// Form with question type boolean
+form testForm {
+ "Question?"
+ var: boolean
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test002.ql b/ql/test/parsing/valid/test002.ql
new file mode 100644
index 0000000..89402fa
--- /dev/null
+++ b/ql/test/parsing/valid/test002.ql
@@ -0,0 +1,5 @@
+// Form with question of type date
+form testForm {
+ "Question?"
+ var: date
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test003.ql b/ql/test/parsing/valid/test003.ql
new file mode 100644
index 0000000..8f8f448
--- /dev/null
+++ b/ql/test/parsing/valid/test003.ql
@@ -0,0 +1,5 @@
+// Form with question of type decimal
+form testForm {
+ "Question?"
+ var: decimal
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test004.ql b/ql/test/parsing/valid/test004.ql
new file mode 100644
index 0000000..7d4b77b
--- /dev/null
+++ b/ql/test/parsing/valid/test004.ql
@@ -0,0 +1,5 @@
+// Form with question of type integer
+form testForm {
+ "Question?"
+ var: integer
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test005.ql b/ql/test/parsing/valid/test005.ql
new file mode 100644
index 0000000..eafc6c1
--- /dev/null
+++ b/ql/test/parsing/valid/test005.ql
@@ -0,0 +1,5 @@
+// Form with question of type money
+form testForm {
+ "Question?"
+ var: money
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test006.ql b/ql/test/parsing/valid/test006.ql
new file mode 100644
index 0000000..16efa4d
--- /dev/null
+++ b/ql/test/parsing/valid/test006.ql
@@ -0,0 +1,5 @@
+// Form with question of type string
+form testForm {
+ "Question?"
+ var: string
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test007.ql b/ql/test/parsing/valid/test007.ql
new file mode 100644
index 0000000..dd2b47a
--- /dev/null
+++ b/ql/test/parsing/valid/test007.ql
@@ -0,0 +1,8 @@
+// Form with two questions with the same identifier
+form testForm {
+ "Question?"
+ var: boolean
+
+ "Question?"
+ var: boolean
+}
diff --git a/ql/test/parsing/valid/test008.ql b/ql/test/parsing/valid/test008.ql
new file mode 100644
index 0000000..20cb866
--- /dev/null
+++ b/ql/test/parsing/valid/test008.ql
@@ -0,0 +1,8 @@
+// Form with two questions with different identifiers
+form testForm {
+ "Question?"
+ var1: boolean
+
+ "Question?"
+ var2: boolean
+}
diff --git a/ql/test/parsing/valid/test009.ql b/ql/test/parsing/valid/test009.ql
new file mode 100644
index 0000000..a4edfa1
--- /dev/null
+++ b/ql/test/parsing/valid/test009.ql
@@ -0,0 +1,20 @@
+// Form with questions of all supported types
+form testForm {
+ "Question?"
+ var1: boolean
+
+ "Question?"
+ var2: date
+
+ "Question?"
+ var3: decimal
+
+ "Question?"
+ var4: integer
+
+ "Question?"
+ var5: money
+
+ "Question?"
+ var6: string
+}
diff --git a/ql/test/parsing/valid/test010.ql b/ql/test/parsing/valid/test010.ql
new file mode 100644
index 0000000..c1985f8
--- /dev/null
+++ b/ql/test/parsing/valid/test010.ql
@@ -0,0 +1,5 @@
+// Form with computed question
+form testForm {
+ "Question?"
+ var: boolean = True
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test011.ql b/ql/test/parsing/valid/test011.ql
new file mode 100644
index 0000000..a59cae6
--- /dev/null
+++ b/ql/test/parsing/valid/test011.ql
@@ -0,0 +1,5 @@
+// Form with computed question
+form testForm {
+ "Question?"
+ var: boolean = False
+} \ No newline at end of file
diff --git a/ql/test/parsing/valid/test012.ql b/ql/test/parsing/valid/test012.ql
new file mode 100644
index 0000000..d745fba
--- /dev/null
+++ b/ql/test/parsing/valid/test012.ql
@@ -0,0 +1,5 @@
+// Form with computed question
+form testForm {
+ "Question?"
+ var: boolean = "ADSADsad"
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/__pycache__/test_semantic_analysis.cpython-35.pyc b/ql/test/semantic_analysis/__pycache__/test_semantic_analysis.cpython-35.pyc
new file mode 100644
index 0000000..5b92465
--- /dev/null
+++ b/ql/test/semantic_analysis/__pycache__/test_semantic_analysis.cpython-35.pyc
Binary files differ
diff --git a/ql/test/semantic_analysis/invalid/test001.ql b/ql/test/semantic_analysis/invalid/test001.ql
new file mode 100644
index 0000000..42b1b41
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test001.ql
@@ -0,0 +1,9 @@
+// Reference to unknown identifier in condition
+form testForm {
+ if (unknownIdentifier) {
+ "First Question"
+ anotherIdentifier : integer
+ }
+ "Second Question"
+ testIdentifier : boolean
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test002.ql b/ql/test/semantic_analysis/invalid/test002.ql
new file mode 100644
index 0000000..856447d
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test002.ql
@@ -0,0 +1,9 @@
+// Reference to unknown identifier in computed question
+form testForm {
+ "First Question"
+ testIdentifier : integer
+ "Second Question"
+ anotherIdentifier : integer = testIdentifier + unknownIdentifier
+}
+
+
diff --git a/ql/test/semantic_analysis/invalid/test003.ql b/ql/test/semantic_analysis/invalid/test003.ql
new file mode 100644
index 0000000..1491a85
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test003.ql
@@ -0,0 +1,13 @@
+// Reference to identifier in condition out of scope
+form testForm {
+ "First Question"
+ testIdentifier : boolean
+ if (testIdentifier) {
+ "Second Question"
+ anotherIdentifier : integer
+ }
+ if (anotherIdentifier) {
+ "Unreachable Question"
+ unreachableIdentifier : integer
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test004.ql b/ql/test/semantic_analysis/invalid/test004.ql
new file mode 100644
index 0000000..5ae3e94
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test004.ql
@@ -0,0 +1,11 @@
+// Reference to identifier in computed question out of scope
+form testForm {
+ "First Question"
+ testIdentifier : boolean
+ if (testIdentifier) {
+ "Second Question"
+ anotherIdentifier : integer
+ }
+ "Third Question"
+ unknownIdentifier : integer = anotherIdentifier + 1
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test005.ql b/ql/test/semantic_analysis/invalid/test005.ql
new file mode 100644
index 0000000..de066f2
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test005.ql
@@ -0,0 +1,5 @@
+// Identifier dependent on itself (reflexive)
+form testForm {
+ "First Question"
+ firstIdentifier : integer = firstIdentifier + 1
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test006.ql b/ql/test/semantic_analysis/invalid/test006.ql
new file mode 100644
index 0000000..12cf8f0
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test006.ql
@@ -0,0 +1,7 @@
+// Identifiers dependent on each other (symmetric)
+form testForm {
+ "First Question"
+ firstIdentifier : integer = secondIdentifier + 1
+ "Second Question"
+ secondIdentifier : integer = firstIdentifier + 1
+}
diff --git a/ql/test/semantic_analysis/invalid/test007.ql b/ql/test/semantic_analysis/invalid/test007.ql
new file mode 100644
index 0000000..08f4f5f
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test007.ql
@@ -0,0 +1,9 @@
+// Identifiers dependent on each other (transitive)
+form testForm {
+ "First Question"
+ firstIdentifier : integer = secondIdentifier + 1
+ "Second Question"
+ secondIdentifier : integer = thirdIdentifier + 1
+ "Third Question"
+ thirdIdentifier : integer = firstIdentifier + 1
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test008.ql b/ql/test/semantic_analysis/invalid/test008.ql
new file mode 100644
index 0000000..6c8a660
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test008.ql
@@ -0,0 +1,7 @@
+// Different questions with equal identifier
+form testForm {
+ "First Question"
+ someIdentifier : integer
+ "Second Question"
+ someIdentifier : decimal
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test009.ql b/ql/test/semantic_analysis/invalid/test009.ql
new file mode 100644
index 0000000..362a2b1
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test009.ql
@@ -0,0 +1,7 @@
+// Equal questions with different types
+form testForm {
+ "First Question"
+ someIdentifier : integer
+ "First Question"
+ someIdentifier : decimal
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test010.ql b/ql/test/semantic_analysis/invalid/test010.ql
new file mode 100644
index 0000000..30a03e2
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test010.ql
@@ -0,0 +1,5 @@
+// Incompatible types for addition operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 + True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test011.ql b/ql/test/semantic_analysis/invalid/test011.ql
new file mode 100644
index 0000000..de59f13
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test011.ql
@@ -0,0 +1,5 @@
+// Incompatible types for subtraction operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 - True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test012.ql b/ql/test/semantic_analysis/invalid/test012.ql
new file mode 100644
index 0000000..006bd0c
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test012.ql
@@ -0,0 +1,5 @@
+// Incompatible types for greater equals operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 >= True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test013.ql b/ql/test/semantic_analysis/invalid/test013.ql
new file mode 100644
index 0000000..2896f80
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test013.ql
@@ -0,0 +1,5 @@
+// Incompatible types for greater than operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 > True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test014.ql b/ql/test/semantic_analysis/invalid/test014.ql
new file mode 100644
index 0000000..b5b7774
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test014.ql
@@ -0,0 +1,5 @@
+// Incompatible types for less equals operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 <= True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test015.ql b/ql/test/semantic_analysis/invalid/test015.ql
new file mode 100644
index 0000000..6c52b37
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test015.ql
@@ -0,0 +1,5 @@
+// Incompatible types for less than operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 < True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test016.ql b/ql/test/semantic_analysis/invalid/test016.ql
new file mode 100644
index 0000000..dcf98ea
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test016.ql
@@ -0,0 +1,5 @@
+// Incompatible types for and operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 && True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test017.ql b/ql/test/semantic_analysis/invalid/test017.ql
new file mode 100644
index 0000000..9eef105
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test017.ql
@@ -0,0 +1,5 @@
+// Incompatible types for or operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 || True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test018.ql b/ql/test/semantic_analysis/invalid/test018.ql
new file mode 100644
index 0000000..bd18cf9
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test018.ql
@@ -0,0 +1,5 @@
+// Incompatible types for multiplication operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 * True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test019.ql b/ql/test/semantic_analysis/invalid/test019.ql
new file mode 100644
index 0000000..69a2c38
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test019.ql
@@ -0,0 +1,5 @@
+// Incompatible types for division operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 / True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test020.ql b/ql/test/semantic_analysis/invalid/test020.ql
new file mode 100644
index 0000000..538bdf9
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test020.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for addition operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.1 + 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test021.ql b/ql/test/semantic_analysis/invalid/test021.ql
new file mode 100644
index 0000000..74e596d
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test021.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for subtraction operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.1 - 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test022.ql b/ql/test/semantic_analysis/invalid/test022.ql
new file mode 100644
index 0000000..9cf774a
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test022.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for greater equals operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.0 >= 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test023.ql b/ql/test/semantic_analysis/invalid/test023.ql
new file mode 100644
index 0000000..f7d674b
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test023.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for greater than operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.0 > 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test024.ql b/ql/test/semantic_analysis/invalid/test024.ql
new file mode 100644
index 0000000..f262f5c
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test024.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for less equals operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.0 <= 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test025.ql b/ql/test/semantic_analysis/invalid/test025.ql
new file mode 100644
index 0000000..ef823b5
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test025.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for less than operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.0 < 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test026.ql b/ql/test/semantic_analysis/invalid/test026.ql
new file mode 100644
index 0000000..b1e8a5b
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test026.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for and operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = True && True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test027.ql b/ql/test/semantic_analysis/invalid/test027.ql
new file mode 100644
index 0000000..262aa0e
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test027.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for or operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = False || True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test028.ql b/ql/test/semantic_analysis/invalid/test028.ql
new file mode 100644
index 0000000..ea02ccd
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test028.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for multiplication operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.1 * 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test029.ql b/ql/test/semantic_analysis/invalid/test029.ql
new file mode 100644
index 0000000..23f3c78
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test029.ql
@@ -0,0 +1,5 @@
+// Incompatible result type for division operation
+form testForm {
+ "First Question"
+ someIdentifier : integer = 10.1 / 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test030.ql b/ql/test/semantic_analysis/invalid/test030.ql
new file mode 100644
index 0000000..3de208c
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test030.ql
@@ -0,0 +1,7 @@
+// Complex condition with incompatible types
+form testForm {
+ if ((15.5 >= 15) && ((3.0 * True) - 15 > -10 / 2)) {
+ "First Question"
+ someIdentifier : integer
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test031.ql b/ql/test/semantic_analysis/invalid/test031.ql
new file mode 100644
index 0000000..0d6f75c
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test031.ql
@@ -0,0 +1,5 @@
+// Complex computed question with incompatible types
+form testForm {
+ "First Question"
+ someIdentifier : boolean = (25.5 >= True) && ((10.0 / 3) - 15 < -10 * 2)
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/invalid/test032.ql b/ql/test/semantic_analysis/invalid/test032.ql
new file mode 100644
index 0000000..9de5ff2
--- /dev/null
+++ b/ql/test/semantic_analysis/invalid/test032.ql
@@ -0,0 +1,5 @@
+// Complex computed question with incompatible result type
+form testForm {
+ "First Question"
+ someIdentifier : integer = (25.5 >= 10) && ((10.0 / 3) - 15 < -10 * 2)
+}
diff --git a/ql/test/semantic_analysis/test_semantic_analysis.py b/ql/test/semantic_analysis/test_semantic_analysis.py
new file mode 100644
index 0000000..ca01231
--- /dev/null
+++ b/ql/test/semantic_analysis/test_semantic_analysis.py
@@ -0,0 +1,39 @@
+from ql.ast.checkers.dependency_checker import DependencyChecker
+from ql.ast.checkers.question_checker import QuestionChecker
+from ql.ast.checkers.reference_checker import ReferenceChecker
+from ql.ast.extractors.extractor import extract_identifier_dependencies
+from ql.ast.extractors.extractor import extract_identifier_scopes
+from ql.ast.extractors.extractor import extract_identifier_types
+from ql.ast.extractors.extractor import extract_questions
+from ql.ast.visitors.type_visitor import TypeVisitor
+from ql.test.test import Test
+
+
+class TestSemanticAnalysis(Test):
+ def __init__(self, directory, lexer, parser):
+ super(TestSemanticAnalysis, self).__init__('semantic analysis', directory)
+ self.__lexer = lexer
+ self.__parser = parser
+
+ def test_file(self, file):
+ ast = self.__parser.parse(file, self.__lexer.lexer)
+
+ reference_errors = ReferenceChecker(extract_identifier_scopes(ast)).errors
+ if reference_errors:
+ return False
+
+ dependency_errors = DependencyChecker(extract_identifier_dependencies(ast)).errors
+ if dependency_errors:
+ return False
+
+ question_errors = QuestionChecker(extract_questions(ast)).errors
+ if question_errors:
+ return False
+
+ type_visitor = TypeVisitor(extract_identifier_types(ast))
+ type_visitor.visit(ast)
+ type_errors = type_visitor.errors
+ if type_errors:
+ return False
+
+ return True
diff --git a/ql/test/semantic_analysis/valid/test001.ql b/ql/test/semantic_analysis/valid/test001.ql
new file mode 100644
index 0000000..d9d037f
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test001.ql
@@ -0,0 +1,9 @@
+// Identifier reference in condition
+form testForm {
+ "First Question"
+ testIdentifier : boolean
+ if (testIdentifier) {
+ "Second Question"
+ anotherIdentifier : integer
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test002.ql b/ql/test/semantic_analysis/valid/test002.ql
new file mode 100644
index 0000000..afe1f5c
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test002.ql
@@ -0,0 +1,7 @@
+// Identifier reference in computed question
+form testForm {
+ "First Question"
+ testIdentifier : integer
+ "Second Question"
+ anotherIdentifier : integer = testIdentifier
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test003.ql b/ql/test/semantic_analysis/valid/test003.ql
new file mode 100644
index 0000000..b89d0c1
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test003.ql
@@ -0,0 +1,9 @@
+// Identifier declared after reference in condition
+form testForm {
+ if (testIdentifier) {
+ "First Question"
+ anotherIdentifier : integer
+ }
+ "Second Question"
+ testIdentifier : boolean
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test004.ql b/ql/test/semantic_analysis/valid/test004.ql
new file mode 100644
index 0000000..8f4feb0
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test004.ql
@@ -0,0 +1,7 @@
+// Identifier declared after reference in computed question
+form testForm {
+ "First Question"
+ anotherIdentifier : integer = testIdentifier + 1
+ "Second Question"
+ testIdentifier : integer
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test005.ql b/ql/test/semantic_analysis/valid/test005.ql
new file mode 100644
index 0000000..8620dc9
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test005.ql
@@ -0,0 +1,15 @@
+// Identifier reference in nested condition
+form testForm {
+ "First Question"
+ firstCondition : boolean
+ "Second Question"
+ secondCondition : boolean
+ if (firstCondition) {
+ "Third Question"
+ anotherIdentifier : integer
+ if (secondCondition) {
+ "Fourth Question"
+ yetAnotherIdentifier : decimal
+ }
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test006.ql b/ql/test/semantic_analysis/valid/test006.ql
new file mode 100644
index 0000000..855332e
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test006.ql
@@ -0,0 +1,13 @@
+// Identifier reference in nested computed question
+form testForm {
+ "First Question"
+ firstCondition : boolean
+ "Second Question"
+ firstInteger : integer
+ if (firstCondition) {
+ "Third Question"
+ anotherIdentifier : integer
+ "Fourth Question"
+ yetAnotherIdentifier : integer = firstInteger + 1
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test007.ql b/ql/test/semantic_analysis/valid/test007.ql
new file mode 100644
index 0000000..1338a82
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test007.ql
@@ -0,0 +1,9 @@
+// Identifier reference in both condition and computed question
+form testForm {
+ "First Question"
+ someInteger : integer
+ if (someInteger > 10) {
+ "Second Question"
+ computedInteger : integer = someInteger - 10
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test008.ql b/ql/test/semantic_analysis/valid/test008.ql
new file mode 100644
index 0000000..80205a5
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test008.ql
@@ -0,0 +1,9 @@
+// Identifier dependant on second, second dependant on third
+form testForm {
+ "First Question"
+ firstIdentifier : integer = secondIdentifier + 1
+ "Second Question"
+ secondIdentifier : integer = thirdIdentifier + 1
+ "Third Question"
+ thirdIdentifier : integer
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test009.ql b/ql/test/semantic_analysis/valid/test009.ql
new file mode 100644
index 0000000..7e92ad7
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test009.ql
@@ -0,0 +1,7 @@
+// Different questions with equal labels
+form testForm {
+ "First Question"
+ someIdentifier : integer
+ "First Question"
+ anotherIdentifier : decimal
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test010.ql b/ql/test/semantic_analysis/valid/test010.ql
new file mode 100644
index 0000000..eca4ad4
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test010.ql
@@ -0,0 +1,5 @@
+// Compatible types for addition operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 + 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test011.ql b/ql/test/semantic_analysis/valid/test011.ql
new file mode 100644
index 0000000..f47b435
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test011.ql
@@ -0,0 +1,5 @@
+// Compatible types for subtraction operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 - 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test012.ql b/ql/test/semantic_analysis/valid/test012.ql
new file mode 100644
index 0000000..2e7e278
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test012.ql
@@ -0,0 +1,5 @@
+// Compatible types for greater equals operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 == 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test013.ql b/ql/test/semantic_analysis/valid/test013.ql
new file mode 100644
index 0000000..a34566c
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test013.ql
@@ -0,0 +1,5 @@
+// Compatible types for greater than operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 > 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test014.ql b/ql/test/semantic_analysis/valid/test014.ql
new file mode 100644
index 0000000..7ee1b86
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test014.ql
@@ -0,0 +1,5 @@
+// Compatible types for less equals operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 <= 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test015.ql b/ql/test/semantic_analysis/valid/test015.ql
new file mode 100644
index 0000000..431c1f0
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test015.ql
@@ -0,0 +1,5 @@
+// Compatible types for less than operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = 10.0 < 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test016.ql b/ql/test/semantic_analysis/valid/test016.ql
new file mode 100644
index 0000000..8b0bdde
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test016.ql
@@ -0,0 +1,5 @@
+// Compatible types for and operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = True && False
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test017.ql b/ql/test/semantic_analysis/valid/test017.ql
new file mode 100644
index 0000000..851e5ff
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test017.ql
@@ -0,0 +1,5 @@
+// Compatible types for or operation
+form testForm {
+ "First Question"
+ someIdentifier : boolean = False || True
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test018.ql b/ql/test/semantic_analysis/valid/test018.ql
new file mode 100644
index 0000000..41d439f
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test018.ql
@@ -0,0 +1,5 @@
+// Compatible types for multiplication operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 * 10
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test019.ql b/ql/test/semantic_analysis/valid/test019.ql
new file mode 100644
index 0000000..36ba458
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test019.ql
@@ -0,0 +1,5 @@
+// Compatible types for division operation
+form testForm {
+ "First Question"
+ someIdentifier : decimal = 10.0 / 10
+}
diff --git a/ql/test/semantic_analysis/valid/test020.ql b/ql/test/semantic_analysis/valid/test020.ql
new file mode 100644
index 0000000..9fff193
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test020.ql
@@ -0,0 +1,7 @@
+// Complex condition with mixed types
+form testForm {
+ if ((15.5 >= 15) && ((3.0 * 3) - 15 > -10 / 2)) {
+ "First Question"
+ someIdentifier : integer
+ }
+} \ No newline at end of file
diff --git a/ql/test/semantic_analysis/valid/test021.ql b/ql/test/semantic_analysis/valid/test021.ql
new file mode 100644
index 0000000..01ec35c
--- /dev/null
+++ b/ql/test/semantic_analysis/valid/test021.ql
@@ -0,0 +1,5 @@
+// Complex computed question with mixed types
+form testForm {
+ "First Question"
+ someIdentifier : boolean = (25.5 >= 10) && ((10.0 / 3) - 15 < -10 * 2)
+} \ No newline at end of file
diff --git a/ql/test/test.py b/ql/test/test.py
new file mode 100644
index 0000000..79b67d4
--- /dev/null
+++ b/ql/test/test.py
@@ -0,0 +1,80 @@
+from os import listdir
+from os import path
+
+from termcolor import colored
+
+
+class Test:
+ def __init__(self, name, directory):
+ self.__name = name
+ self.directory = directory
+ self.valid_files = self.get_directory_files(directory + 'valid')
+ self.invalid_files = self.get_directory_files(directory + 'invalid')
+
+ @property
+ def name(self):
+ return self.__name
+
+ @staticmethod
+ def get_directory_files(directory):
+ if path.exists(directory):
+ return sorted(listdir(directory))
+
+ return []
+
+ def test(self):
+ successes = 0
+ print('-------------------------------------------------------------------------------------------\n')
+ print('Performing {} tests.\n'.format(self.name))
+ print('-------------------------------------------------------------------------------------------\n')
+
+ if self.valid_files:
+ print('Performing valid tests:')
+ successes += self.test_valid_files()
+ print()
+
+ if self.invalid_files:
+ print('Performing invalid tests:')
+ successes += self.test_invalid_files()
+ print()
+
+ print('{} out of {} {} tests successful.\n'.format(successes, len(self.valid_files) + len(self.invalid_files),
+ self.name))
+
+ def test_file(self, file):
+ pass
+
+ def test_valid_files(self, valid=True):
+ successes = 0
+
+ for file in self.valid_files:
+ test = open(self.directory + 'valid/' + file, 'r').read()
+ result = valid == self.test_file(test)
+ self.print_result(file, result, test.split('\n')[0])
+
+ if result:
+ successes += 1
+
+ return successes
+
+ def test_invalid_files(self, valid=False):
+ successes = 0
+
+ for file in self.invalid_files:
+ test = open(self.directory + 'invalid/' + file, 'r').read()
+ result = valid == self.test_file(test)
+ self.print_result(file, result, test.split('\n')[0])
+
+ if result:
+ successes += 1
+
+ return successes
+
+ @staticmethod
+ def print_result(file, result=True, test=''):
+ tag = colored('[failure]', 'red')
+
+ if result:
+ tag = colored('[success]', 'green')
+
+ print(tag, file, test.strip('//').strip())