aboutsummaryrefslogtreecommitdiff
path: root/ql
diff options
context:
space:
mode:
Diffstat (limited to 'ql')
-rw-r--r--ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pycbin0 -> 1953 bytes
-rw-r--r--ql/ast/checkers/__pycache__/question_checker.cpython-35.pycbin0 -> 1658 bytes
-rw-r--r--ql/ast/checkers/__pycache__/reference_checker.cpython-35.pycbin0 -> 2061 bytes
-rw-r--r--ql/ast/checkers/dependency_checker.py44
-rw-r--r--ql/ast/checkers/question_checker.py33
-rw-r--r--ql/ast/checkers/reference_checker.py30
-rw-r--r--ql/ast/extractors/__pycache__/extractor.cpython-35.pycbin0 -> 1540 bytes
-rw-r--r--ql/ast/extractors/extractor.py35
-rw-r--r--ql/ast/nodes/__pycache__/base.cpython-35.pycbin0 -> 764 bytes
-rw-r--r--ql/ast/nodes/base.py10
-rw-r--r--ql/ast/nodes/expressions/__pycache__/expression.cpython-35.pycbin0 -> 1222 bytes
-rw-r--r--ql/ast/nodes/expressions/__pycache__/variable.cpython-35.pycbin0 -> 843 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/addition_operator.cpython-35.pycbin0 -> 1523 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/and_operator.cpython-35.pycbin0 -> 1325 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/binary_operator.cpython-35.pycbin0 -> 1117 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/division_operator.cpython-35.pycbin0 -> 1604 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/equals_operator.cpython-35.pycbin0 -> 1142 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/greater_equals_operator.cpython-35.pycbin0 -> 1626 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/greater_than_operator.cpython-35.pycbin0 -> 1614 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/less_equals_operator.cpython-35.pycbin0 -> 1608 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/less_than_operator.cpython-35.pycbin0 -> 1596 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/multiplication_operator.cpython-35.pycbin0 -> 1601 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/not_equals_operator.cpython-35.pycbin0 -> 1158 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/or_operator.cpython-35.pycbin0 -> 1319 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/__pycache__/subtraction_operator.cpython-35.pycbin0 -> 1541 bytes
-rw-r--r--ql/ast/nodes/expressions/binary_operators/addition_operator.py27
-rw-r--r--ql/ast/nodes/expressions/binary_operators/and_operator.py21
-rw-r--r--ql/ast/nodes/expressions/binary_operators/binary_operator.py17
-rw-r--r--ql/ast/nodes/expressions/binary_operators/division_operator.py31
-rw-r--r--ql/ast/nodes/expressions/binary_operators/equals_operator.py15
-rw-r--r--ql/ast/nodes/expressions/binary_operators/greater_equals_operator.py30
-rw-r--r--ql/ast/nodes/expressions/binary_operators/greater_than_operator.py30
-rw-r--r--ql/ast/nodes/expressions/binary_operators/less_equals_operator.py30
-rw-r--r--ql/ast/nodes/expressions/binary_operators/less_than_operator.py30
-rw-r--r--ql/ast/nodes/expressions/binary_operators/multiplication_operator.py30
-rw-r--r--ql/ast/nodes/expressions/binary_operators/not_equals_operator.py15
-rw-r--r--ql/ast/nodes/expressions/binary_operators/or_operator.py21
-rw-r--r--ql/ast/nodes/expressions/binary_operators/subtraction_operator.py27
-rw-r--r--ql/ast/nodes/expressions/expression.py24
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/boolean_literal.cpython-35.pycbin0 -> 669 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/date_literal.cpython-35.pycbin0 -> 660 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/decimal_literal.cpython-35.pycbin0 -> 669 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/integer_literal.cpython-35.pycbin0 -> 669 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/literal.cpython-35.pycbin0 -> 946 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/money_literal.cpython-35.pycbin0 -> 663 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/string_literal.cpython-35.pycbin0 -> 666 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/__pycache__/undefined_literal.cpython-35.pycbin0 -> 675 bytes
-rw-r--r--ql/ast/nodes/expressions/literals/boolean_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/date_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/decimal_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/integer_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/literal.py14
-rw-r--r--ql/ast/nodes/expressions/literals/money_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/string_literal.py6
-rw-r--r--ql/ast/nodes/expressions/literals/undefined_literal.py6
-rw-r--r--ql/ast/nodes/expressions/unary_operators/__pycache__/negation_operator.cpython-35.pycbin0 -> 1283 bytes
-rw-r--r--ql/ast/nodes/expressions/unary_operators/__pycache__/negative_operator.cpython-35.pycbin0 -> 1402 bytes
-rw-r--r--ql/ast/nodes/expressions/unary_operators/__pycache__/unary_operator.cpython-35.pycbin0 -> 885 bytes
-rw-r--r--ql/ast/nodes/expressions/unary_operators/negation_operator.py20
-rw-r--r--ql/ast/nodes/expressions/unary_operators/negative_operator.py23
-rw-r--r--ql/ast/nodes/expressions/unary_operators/unary_operator.py11
-rw-r--r--ql/ast/nodes/expressions/variable.py11
-rw-r--r--ql/ast/nodes/statements/__pycache__/block_statement.cpython-35.pycbin0 -> 804 bytes
-rw-r--r--ql/ast/nodes/statements/__pycache__/form_statement.cpython-35.pycbin0 -> 820 bytes
-rw-r--r--ql/ast/nodes/statements/__pycache__/if_statement.cpython-35.pycbin0 -> 807 bytes
-rw-r--r--ql/ast/nodes/statements/__pycache__/question_statement.cpython-35.pycbin0 -> 1495 bytes
-rw-r--r--ql/ast/nodes/statements/block_statement.py11
-rw-r--r--ql/ast/nodes/statements/form_statement.py12
-rw-r--r--ql/ast/nodes/statements/if_statement.py11
-rw-r--r--ql/ast/nodes/statements/question_statement.py31
-rw-r--r--ql/ast/visitors/__pycache__/dependency_visitor.cpython-35.pycbin0 -> 2626 bytes
-rw-r--r--ql/ast/visitors/__pycache__/expression_evaluator.cpython-35.pycbin0 -> 1834 bytes
-rw-r--r--ql/ast/visitors/__pycache__/identifier_type_visitor.cpython-35.pycbin0 -> 1552 bytes
-rw-r--r--ql/ast/visitors/__pycache__/model_generator.cpython-35.pycbin0 -> 1918 bytes
-rw-r--r--ql/ast/visitors/__pycache__/question_visitor.cpython-35.pycbin0 -> 1555 bytes
-rw-r--r--ql/ast/visitors/__pycache__/reference_visitor.cpython-35.pycbin0 -> 2997 bytes
-rw-r--r--ql/ast/visitors/__pycache__/type_visitor.cpython-35.pycbin0 -> 3387 bytes
-rw-r--r--ql/ast/visitors/dependency_visitor.py54
-rw-r--r--ql/ast/visitors/expression_evaluator.py37
-rw-r--r--ql/ast/visitors/identifier_type_visitor.py31
-rw-r--r--ql/ast/visitors/model_generator.py39
-rw-r--r--ql/ast/visitors/question_visitor.py33
-rw-r--r--ql/ast/visitors/reference_visitor.py86
-rw-r--r--ql/ast/visitors/type_visitor.py85
-rw-r--r--ql/parser/__pycache__/lexer.cpython-35.pycbin0 -> 4275 bytes
-rw-r--r--ql/parser/__pycache__/metadata.cpython-35.pycbin0 -> 612 bytes
-rw-r--r--ql/parser/__pycache__/parser.cpython-35.pycbin0 -> 14851 bytes
-rw-r--r--ql/parser/__pycache__/parsetab.cpython-35.pycbin0 -> 12432 bytes
-rw-r--r--ql/parser/lexer.py153
-rw-r--r--ql/parser/metadata.py7
-rw-r--r--ql/parser/parser.out2214
-rw-r--r--ql/parser/parser.py319
-rw-r--r--ql/parser/parsetab.py76
-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
-rw-r--r--ql/types/__pycache__/boolean.cpython-35.pycbin0 -> 2085 bytes
-rw-r--r--ql/types/__pycache__/date.cpython-35.pycbin0 -> 3328 bytes
-rw-r--r--ql/types/__pycache__/decimal.cpython-35.pycbin0 -> 3514 bytes
-rw-r--r--ql/types/__pycache__/integer.cpython-35.pycbin0 -> 3568 bytes
-rw-r--r--ql/types/__pycache__/money.cpython-35.pycbin0 -> 3747 bytes
-rw-r--r--ql/types/__pycache__/string.cpython-35.pycbin0 -> 2788 bytes
-rw-r--r--ql/types/__pycache__/type.cpython-35.pycbin0 -> 443 bytes
-rw-r--r--ql/types/__pycache__/undefined.cpython-35.pycbin0 -> 2013 bytes
-rw-r--r--ql/types/boolean.py42
-rw-r--r--ql/types/date.py67
-rw-r--r--ql/types/decimal.py74
-rw-r--r--ql/types/integer.py75
-rw-r--r--ql/types/money.py76
-rw-r--r--ql/types/string.py55
-rw-r--r--ql/types/type.py3
-rw-r--r--ql/types/undefined.py40
277 files changed, 5140 insertions, 0 deletions
diff --git a/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc
new file mode 100644
index 0000000..5be2eb2
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc
new file mode 100644
index 0000000..bb81f4a
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc
new file mode 100644
index 0000000..3bdfae5
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/dependency_checker.py b/ql/ast/checkers/dependency_checker.py
new file mode 100644
index 0000000..473ef6b
--- /dev/null
+++ b/ql/ast/checkers/dependency_checker.py
@@ -0,0 +1,44 @@
+class DependencyChecker:
+ def __init__(self, combinations):
+ self.__errors = []
+ self.__check_dependencies(combinations)
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ def __check_dependencies(self, combinations):
+ for (identifier, identifier_children, identifier_metadata) in combinations:
+ children = self.__find_children(identifier, combinations)
+
+ if identifier in children:
+ self.__errors.append('Cyclic dependency detected in question identifiers on line(s) {}'
+ .format(str(self.__find_lines(children, combinations))[1:-1]))
+
+ def __find_children(self, identifier, combinations):
+ reference, reference_children, _ = combinations[0]
+
+ if len(combinations) == 1 and identifier == reference:
+ return reference_children
+ elif len(combinations) == 1:
+ return []
+ elif identifier == reference:
+ all_children = []
+
+ for new_identifier in reference_children:
+ all_children += self.__find_children(new_identifier, combinations[1:])
+
+ return all_children + reference_children
+
+ return self.__find_children(identifier, combinations[1:])
+
+ @staticmethod
+ def __find_lines(children, combinations):
+ lines = []
+
+ for identifier, _, metadata in combinations:
+ for child in children:
+ if identifier == child:
+ lines.append(metadata.line)
+
+ return lines
diff --git a/ql/ast/checkers/question_checker.py b/ql/ast/checkers/question_checker.py
new file mode 100644
index 0000000..5b255d8
--- /dev/null
+++ b/ql/ast/checkers/question_checker.py
@@ -0,0 +1,33 @@
+class QuestionChecker:
+ def __init__(self, questions):
+ self.__errors = []
+ self.__warnings = []
+ self.__check_questions(questions)
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ @property
+ def warnings(self):
+ return self.__warnings
+
+ def __check_questions(self, questions):
+ for question1 in questions:
+ for question2 in questions:
+ if question1 != question2:
+ equal_labels = question1['label'] == question2['label']
+ equal_identifiers = question1['identifier'] == question2['identifier']
+ different_types = question1['answer_type'] != question2['answer_type']
+
+ if all([equal_labels, equal_identifiers, different_types]):
+ self.__errors.append('Duplicate questions with different types found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
+
+ if equal_identifiers:
+ self.__errors.append('Duplicate question identifiers found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
+
+ if equal_labels:
+ self.__warnings.append('Duplicate question labels found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
diff --git a/ql/ast/checkers/reference_checker.py b/ql/ast/checkers/reference_checker.py
new file mode 100644
index 0000000..71407c3
--- /dev/null
+++ b/ql/ast/checkers/reference_checker.py
@@ -0,0 +1,30 @@
+class ReferenceChecker:
+ def __init__(self, table):
+ self.__errors = []
+ self.__check_references(table, [], [])
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ def __check_references(self, table, known_types, unknown_types):
+ (local_known_types, local_unknown_types) = self.__split_known_unknown_types(table)
+ known_types += local_known_types
+ unknown_types += local_unknown_types
+
+ self.__identifier_seen(known_types, unknown_types)
+
+ if table['children']:
+ for child_scope in table['children']:
+ self.__check_references(child_scope, known_types, unknown_types)
+
+ @staticmethod
+ def __split_known_unknown_types(table):
+ known_types = [row['name'] for row in table['content'] if row['type']]
+ unknown_types = [(row['name'], row['line']) for row in table['content'] if not (row['type'])]
+ return known_types, unknown_types
+
+ def __identifier_seen(self, known_types, unknown_types):
+ for (identifier, line) in unknown_types:
+ if not (identifier in known_types):
+ self.__errors.append('Identifier \"{}\" at line {} is unknown'.format(identifier, line))
diff --git a/ql/ast/extractors/__pycache__/extractor.cpython-35.pyc b/ql/ast/extractors/__pycache__/extractor.cpython-35.pyc
new file mode 100644
index 0000000..ceb2379
--- /dev/null
+++ b/ql/ast/extractors/__pycache__/extractor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/extractors/extractor.py b/ql/ast/extractors/extractor.py
new file mode 100644
index 0000000..f86304e
--- /dev/null
+++ b/ql/ast/extractors/extractor.py
@@ -0,0 +1,35 @@
+from ql.ast.visitors.dependency_visitor import DependencyVisitor
+from ql.ast.visitors.identifier_type_visitor import IdentifierTypeVisitor
+from ql.ast.visitors.model_generator import ModelGenerator
+from ql.ast.visitors.question_visitor import QuestionVisitor
+from ql.ast.visitors.reference_visitor import ReferenceVisitor
+
+
+def extract_identifier_dependencies(ast):
+ dependency_visitor = DependencyVisitor()
+ dependency_visitor.visit(ast)
+ return dependency_visitor.identifier_dependencies
+
+
+def extract_identifier_scopes(ast):
+ reference_visitor = ReferenceVisitor()
+ reference_visitor.visit(ast)
+ return reference_visitor.identifier_scopes
+
+
+def extract_identifier_types(ast):
+ identifier_type_visitor = IdentifierTypeVisitor()
+ identifier_type_visitor.visit(ast)
+ return identifier_type_visitor.symbol_table
+
+
+def extract_questions(ast):
+ question_visitor = QuestionVisitor()
+ question_visitor.visit(ast)
+ return question_visitor.questions
+
+
+def extract_gui_model(ast):
+ model_generator = ModelGenerator()
+ model_generator.visit(ast)
+ return model_generator.form
diff --git a/ql/ast/nodes/__pycache__/base.cpython-35.pyc b/ql/ast/nodes/__pycache__/base.cpython-35.pyc
new file mode 100644
index 0000000..d1f8e50
--- /dev/null
+++ b/ql/ast/nodes/__pycache__/base.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/base.py b/ql/ast/nodes/base.py
new file mode 100644
index 0000000..d9196f9
--- /dev/null
+++ b/ql/ast/nodes/base.py
@@ -0,0 +1,10 @@
+class BaseNode:
+ def __init__(self, metadata):
+ self.__metadata = metadata
+
+ def accept(self, visitor):
+ visitor.visit(self)
+
+ @property
+ def metadata(self):
+ return self.__metadata
diff --git a/ql/ast/nodes/expressions/__pycache__/expression.cpython-35.pyc b/ql/ast/nodes/expressions/__pycache__/expression.cpython-35.pyc
new file mode 100644
index 0000000..84ede5c
--- /dev/null
+++ b/ql/ast/nodes/expressions/__pycache__/expression.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/__pycache__/variable.cpython-35.pyc b/ql/ast/nodes/expressions/__pycache__/variable.cpython-35.pyc
new file mode 100644
index 0000000..b4ff8dc
--- /dev/null
+++ b/ql/ast/nodes/expressions/__pycache__/variable.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/addition_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/addition_operator.cpython-35.pyc
new file mode 100644
index 0000000..bbc8130
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/addition_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/and_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/and_operator.cpython-35.pyc
new file mode 100644
index 0000000..f004296
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/and_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/binary_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/binary_operator.cpython-35.pyc
new file mode 100644
index 0000000..18d3fc0
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/binary_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/division_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/division_operator.cpython-35.pyc
new file mode 100644
index 0000000..9cd8e0a
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/division_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/equals_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/equals_operator.cpython-35.pyc
new file mode 100644
index 0000000..5d48766
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/equals_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_equals_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_equals_operator.cpython-35.pyc
new file mode 100644
index 0000000..888c85c
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_equals_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_than_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_than_operator.cpython-35.pyc
new file mode 100644
index 0000000..be0e395
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/greater_than_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/less_equals_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/less_equals_operator.cpython-35.pyc
new file mode 100644
index 0000000..b7e8155
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/less_equals_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/less_than_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/less_than_operator.cpython-35.pyc
new file mode 100644
index 0000000..850a39c
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/less_than_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/multiplication_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/multiplication_operator.cpython-35.pyc
new file mode 100644
index 0000000..ff0e1ab
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/multiplication_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/not_equals_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/not_equals_operator.cpython-35.pyc
new file mode 100644
index 0000000..fe666cf
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/not_equals_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/or_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/or_operator.cpython-35.pyc
new file mode 100644
index 0000000..0b81fc3
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/or_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/__pycache__/subtraction_operator.cpython-35.pyc b/ql/ast/nodes/expressions/binary_operators/__pycache__/subtraction_operator.cpython-35.pyc
new file mode 100644
index 0000000..cd89879
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/__pycache__/subtraction_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/binary_operators/addition_operator.py b/ql/ast/nodes/expressions/binary_operators/addition_operator.py
new file mode 100644
index 0000000..d6e4506
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/addition_operator.py
@@ -0,0 +1,27 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.undefined import QLUndefined
+
+
+class AdditionOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(AdditionOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLDecimal, QLDecimal): QLDecimal,
+ (QLDecimal, QLInteger): QLDecimal,
+ (QLInteger, QLInteger): QLInteger,
+ (QLInteger, QLDecimal): QLDecimal,
+ (QLMoney, QLMoney): QLMoney,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value + self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/and_operator.py b/ql/ast/nodes/expressions/binary_operators/and_operator.py
new file mode 100644
index 0000000..5981a6b
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/and_operator.py
@@ -0,0 +1,21 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.boolean import QLBoolean
+from ql.types.undefined import QLUndefined
+
+
+class AndOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(AndOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLBoolean, QLBoolean): QLBoolean,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value and self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/binary_operator.py b/ql/ast/nodes/expressions/binary_operators/binary_operator.py
new file mode 100644
index 0000000..048d927
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/binary_operator.py
@@ -0,0 +1,17 @@
+from ql.ast.nodes.expressions.expression import ExpressionNode
+
+
+class BinaryOperatorNode(ExpressionNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(BinaryOperatorNode, self).__init__(metadata, expression_type, value)
+ self.__left_expression = left_expression
+ self.__right_expression = right_expression
+
+ @property
+ def left_expression(self):
+ return self.__left_expression
+
+ @property
+ def right_expression(self):
+ return self.__right_expression
+
diff --git a/ql/ast/nodes/expressions/binary_operators/division_operator.py b/ql/ast/nodes/expressions/binary_operators/division_operator.py
new file mode 100644
index 0000000..16d5063
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/division_operator.py
@@ -0,0 +1,31 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.undefined import QLUndefined
+
+
+class DivisionOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(DivisionOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLDecimal, QLDecimal): QLDecimal,
+ (QLDecimal, QLInteger): QLDecimal,
+ (QLInteger, QLInteger): QLDecimal,
+ (QLInteger, QLDecimal): QLDecimal,
+ (QLMoney, QLDecimal): QLMoney,
+ (QLMoney, QLInteger): QLMoney,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ try:
+ self.value = self.left_expression.value / self.right_expression.value
+ except ZeroDivisionError:
+ self.value = QLUndefined()
diff --git a/ql/ast/nodes/expressions/binary_operators/equals_operator.py b/ql/ast/nodes/expressions/binary_operators/equals_operator.py
new file mode 100644
index 0000000..21315f9
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/equals_operator.py
@@ -0,0 +1,15 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.boolean import QLBoolean
+
+
+class EqualsOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(EqualsOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+
+ @staticmethod
+ def get_result_type():
+ return QLBoolean
+
+ def evaluate(self):
+ self.value = self.left_expression.value == self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/greater_equals_operator.py b/ql/ast/nodes/expressions/binary_operators/greater_equals_operator.py
new file mode 100644
index 0000000..0512688
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/greater_equals_operator.py
@@ -0,0 +1,30 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+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.undefined import QLUndefined
+
+
+class GreaterEqualsOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(GreaterEqualsOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = [
+ (QLDate, QLDate),
+ (QLDecimal, QLDecimal),
+ (QLDecimal, QLInteger),
+ (QLInteger, QLInteger),
+ (QLInteger, QLDecimal),
+ (QLMoney, QLMoney),
+ ]
+
+ def get_result_type(self):
+ if (self.left_expression.expression_type, self.right_expression.expression_type) in self.__valid_types:
+ return QLBoolean
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value >= self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/greater_than_operator.py b/ql/ast/nodes/expressions/binary_operators/greater_than_operator.py
new file mode 100644
index 0000000..460c909
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/greater_than_operator.py
@@ -0,0 +1,30 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+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.undefined import QLUndefined
+
+
+class GreaterThanOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(GreaterThanOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = [
+ (QLDate, QLDate),
+ (QLDecimal, QLDecimal),
+ (QLDecimal, QLInteger),
+ (QLInteger, QLInteger),
+ (QLInteger, QLDecimal),
+ (QLMoney, QLMoney),
+ ]
+
+ def get_result_type(self):
+ if (self.left_expression.expression_type, self.right_expression.expression_type) in self.__valid_types:
+ return QLBoolean
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value > self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/less_equals_operator.py b/ql/ast/nodes/expressions/binary_operators/less_equals_operator.py
new file mode 100644
index 0000000..f5b86df
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/less_equals_operator.py
@@ -0,0 +1,30 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+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.undefined import QLUndefined
+
+
+class LessEqualsOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(LessEqualsOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = [
+ (QLDate, QLDate),
+ (QLDecimal, QLDecimal),
+ (QLDecimal, QLInteger),
+ (QLInteger, QLInteger),
+ (QLInteger, QLDecimal),
+ (QLMoney, QLMoney),
+ ]
+
+ def get_result_type(self):
+ if (self.left_expression.expression_type, self.right_expression.expression_type) in self.__valid_types:
+ return QLBoolean
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value <= self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/less_than_operator.py b/ql/ast/nodes/expressions/binary_operators/less_than_operator.py
new file mode 100644
index 0000000..65b456d
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/less_than_operator.py
@@ -0,0 +1,30 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+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.undefined import QLUndefined
+
+
+class LessThanOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(LessThanOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = [
+ (QLDate, QLDate),
+ (QLDecimal, QLDecimal),
+ (QLDecimal, QLInteger),
+ (QLInteger, QLInteger),
+ (QLInteger, QLDecimal),
+ (QLMoney, QLMoney),
+ ]
+
+ def get_result_type(self):
+ if (self.left_expression.expression_type, self.right_expression.expression_type) in self.__valid_types:
+ return QLBoolean
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value < self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/multiplication_operator.py b/ql/ast/nodes/expressions/binary_operators/multiplication_operator.py
new file mode 100644
index 0000000..b014c0e
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/multiplication_operator.py
@@ -0,0 +1,30 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.undefined import QLUndefined
+
+
+class MultiplicationOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(MultiplicationOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLDecimal, QLDecimal): QLDecimal,
+ (QLDecimal, QLInteger): QLDecimal,
+ (QLDecimal, QLMoney): QLMoney,
+ (QLInteger, QLInteger): QLInteger,
+ (QLInteger, QLDecimal): QLDecimal,
+ (QLInteger, QLMoney): QLMoney,
+ (QLMoney, QLDecimal): QLMoney,
+ (QLMoney, QLInteger): QLMoney,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value * self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/not_equals_operator.py b/ql/ast/nodes/expressions/binary_operators/not_equals_operator.py
new file mode 100644
index 0000000..3be2e5f
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/not_equals_operator.py
@@ -0,0 +1,15 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.boolean import QLBoolean
+
+
+class NotEqualsOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(NotEqualsOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+
+ @staticmethod
+ def get_result_type():
+ return QLBoolean
+
+ def evaluate(self):
+ self.value = self.left_expression.value != self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/or_operator.py b/ql/ast/nodes/expressions/binary_operators/or_operator.py
new file mode 100644
index 0000000..4314868
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/or_operator.py
@@ -0,0 +1,21 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.boolean import QLBoolean
+from ql.types.undefined import QLUndefined
+
+
+class OrOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(OrOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLBoolean, QLBoolean): QLBoolean,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value or self.right_expression.value
diff --git a/ql/ast/nodes/expressions/binary_operators/subtraction_operator.py b/ql/ast/nodes/expressions/binary_operators/subtraction_operator.py
new file mode 100644
index 0000000..8ebda15
--- /dev/null
+++ b/ql/ast/nodes/expressions/binary_operators/subtraction_operator.py
@@ -0,0 +1,27 @@
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.undefined import QLUndefined
+
+
+class SubtractionOperatorNode(BinaryOperatorNode):
+ def __init__(self, metadata, expression_type, left_expression, right_expression, value):
+ super(SubtractionOperatorNode, self).__init__(metadata, expression_type,
+ left_expression, right_expression, value)
+ self.__valid_types = {
+ (QLDecimal, QLDecimal): QLDecimal,
+ (QLDecimal, QLInteger): QLDecimal,
+ (QLInteger, QLInteger): QLInteger,
+ (QLInteger, QLDecimal): QLDecimal,
+ (QLMoney, QLMoney): QLMoney,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type)):
+ return self.__valid_types.get((self.left_expression.expression_type, self.right_expression.expression_type))
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = self.left_expression.value - self.right_expression.value
diff --git a/ql/ast/nodes/expressions/expression.py b/ql/ast/nodes/expressions/expression.py
new file mode 100644
index 0000000..1364c0b
--- /dev/null
+++ b/ql/ast/nodes/expressions/expression.py
@@ -0,0 +1,24 @@
+from ql.ast.nodes.base import BaseNode
+
+
+class ExpressionNode(BaseNode):
+ def __init__(self, metadata, expression_type, value):
+ super(ExpressionNode, self).__init__(metadata)
+ self.__expression_type = expression_type
+ self.__value = value
+
+ @property
+ def expression_type(self):
+ return self.__expression_type
+
+ @expression_type.setter
+ def expression_type(self, value):
+ self.__expression_type = value
+
+ @property
+ def value(self):
+ return self.__value
+
+ @value.setter
+ def value(self, value):
+ self.__value = value
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/boolean_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/boolean_literal.cpython-35.pyc
new file mode 100644
index 0000000..a6d43b1
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/boolean_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/date_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/date_literal.cpython-35.pyc
new file mode 100644
index 0000000..33abf57
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/date_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/decimal_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/decimal_literal.cpython-35.pyc
new file mode 100644
index 0000000..145ab16
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/decimal_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/integer_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/integer_literal.cpython-35.pyc
new file mode 100644
index 0000000..33f5c62
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/integer_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/literal.cpython-35.pyc
new file mode 100644
index 0000000..98af8e6
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/money_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/money_literal.cpython-35.pyc
new file mode 100644
index 0000000..9dbf5d0
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/money_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/string_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/string_literal.cpython-35.pyc
new file mode 100644
index 0000000..dbb3f72
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/string_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/__pycache__/undefined_literal.cpython-35.pyc b/ql/ast/nodes/expressions/literals/__pycache__/undefined_literal.cpython-35.pyc
new file mode 100644
index 0000000..73ce02b
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/__pycache__/undefined_literal.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/literals/boolean_literal.py b/ql/ast/nodes/expressions/literals/boolean_literal.py
new file mode 100644
index 0000000..234e548
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/boolean_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class BooleanNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(BooleanNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/date_literal.py b/ql/ast/nodes/expressions/literals/date_literal.py
new file mode 100644
index 0000000..971ab58
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/date_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class DateNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(DateNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/decimal_literal.py b/ql/ast/nodes/expressions/literals/decimal_literal.py
new file mode 100644
index 0000000..7cc4eb5
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/decimal_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class DecimalNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(DecimalNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/integer_literal.py b/ql/ast/nodes/expressions/literals/integer_literal.py
new file mode 100644
index 0000000..36923f9
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/integer_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class IntegerNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(IntegerNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/literal.py b/ql/ast/nodes/expressions/literals/literal.py
new file mode 100644
index 0000000..a0e03ae
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/literal.py
@@ -0,0 +1,14 @@
+from ql.ast.nodes.expressions.expression import ExpressionNode
+
+
+class LiteralNode(ExpressionNode):
+ def __init__(self, metadata, expression_type, value):
+ super(LiteralNode, self).__init__(metadata, expression_type, value)
+
+ @ExpressionNode.expression_type.setter
+ def expression_type(self, unused):
+ pass
+
+ @ExpressionNode.value.setter
+ def value(self, unused):
+ pass
diff --git a/ql/ast/nodes/expressions/literals/money_literal.py b/ql/ast/nodes/expressions/literals/money_literal.py
new file mode 100644
index 0000000..119e5ff
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/money_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class MoneyNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(MoneyNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/string_literal.py b/ql/ast/nodes/expressions/literals/string_literal.py
new file mode 100644
index 0000000..4fac895
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/string_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class StringNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(StringNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/literals/undefined_literal.py b/ql/ast/nodes/expressions/literals/undefined_literal.py
new file mode 100644
index 0000000..4109df6
--- /dev/null
+++ b/ql/ast/nodes/expressions/literals/undefined_literal.py
@@ -0,0 +1,6 @@
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+
+
+class UndefinedNode(LiteralNode):
+ def __init__(self, metadata, expression_type, value):
+ super(UndefinedNode, self).__init__(metadata, expression_type, value)
diff --git a/ql/ast/nodes/expressions/unary_operators/__pycache__/negation_operator.cpython-35.pyc b/ql/ast/nodes/expressions/unary_operators/__pycache__/negation_operator.cpython-35.pyc
new file mode 100644
index 0000000..9a6e409
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/__pycache__/negation_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/unary_operators/__pycache__/negative_operator.cpython-35.pyc b/ql/ast/nodes/expressions/unary_operators/__pycache__/negative_operator.cpython-35.pyc
new file mode 100644
index 0000000..45ad495
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/__pycache__/negative_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/unary_operators/__pycache__/unary_operator.cpython-35.pyc b/ql/ast/nodes/expressions/unary_operators/__pycache__/unary_operator.cpython-35.pyc
new file mode 100644
index 0000000..f72b4f0
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/__pycache__/unary_operator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/expressions/unary_operators/negation_operator.py b/ql/ast/nodes/expressions/unary_operators/negation_operator.py
new file mode 100644
index 0000000..7b6b0c5
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/negation_operator.py
@@ -0,0 +1,20 @@
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.types.boolean import QLBoolean
+from ql.types.undefined import QLUndefined
+
+
+class NegationOperatorNode(UnaryOperatorNode):
+ def __init__(self, metadata, expression_type, expression, value):
+ super(NegationOperatorNode, self).__init__(metadata, expression_type, expression, value)
+ self.__valid_types = {
+ QLBoolean: QLBoolean,
+ }
+
+ def get_result_type(self):
+ if self.__valid_types.get(self.expression.expression_type):
+ return self.__valid_types.get(self.expression.expression_type)
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = QLBoolean(not self.expression.value)
diff --git a/ql/ast/nodes/expressions/unary_operators/negative_operator.py b/ql/ast/nodes/expressions/unary_operators/negative_operator.py
new file mode 100644
index 0000000..359ed2e
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/negative_operator.py
@@ -0,0 +1,23 @@
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.types.decimal import QLDecimal
+from ql.types.integer import QLInteger
+from ql.types.money import QLMoney
+from ql.types.undefined import QLUndefined
+
+
+class NegativeOperatorNode(UnaryOperatorNode):
+ def __init__(self, metadata, expression_type, expression, value):
+ super(NegativeOperatorNode, self).__init__(metadata, expression_type, expression, value)
+ self.__valid_types = {
+ QLDecimal: QLDecimal,
+ QLInteger: QLInteger,
+ QLMoney: QLMoney}
+
+ def get_result_type(self):
+ if self.__valid_types.get(self.expression.expression_type):
+ return self.__valid_types.get(self.expression.expression_type)
+
+ return QLUndefined
+
+ def evaluate(self):
+ self.value = -self.expression.value
diff --git a/ql/ast/nodes/expressions/unary_operators/unary_operator.py b/ql/ast/nodes/expressions/unary_operators/unary_operator.py
new file mode 100644
index 0000000..fa75249
--- /dev/null
+++ b/ql/ast/nodes/expressions/unary_operators/unary_operator.py
@@ -0,0 +1,11 @@
+from ql.ast.nodes.expressions.expression import ExpressionNode
+
+
+class UnaryOperatorNode(ExpressionNode):
+ def __init__(self, metadata, expression_type, expression, value):
+ super(UnaryOperatorNode, self).__init__(metadata, expression_type, value)
+ self.__expression = expression
+
+ @property
+ def expression(self):
+ return self.__expression
diff --git a/ql/ast/nodes/expressions/variable.py b/ql/ast/nodes/expressions/variable.py
new file mode 100644
index 0000000..c126372
--- /dev/null
+++ b/ql/ast/nodes/expressions/variable.py
@@ -0,0 +1,11 @@
+from ql.ast.nodes.expressions.expression import ExpressionNode
+
+
+class VariableNode(ExpressionNode):
+ def __init__(self, metadata, expression_type, identifier, value):
+ super(VariableNode, self).__init__(metadata, expression_type, value)
+ self.__identifier = identifier
+
+ @property
+ def identifier(self):
+ return self.__identifier
diff --git a/ql/ast/nodes/statements/__pycache__/block_statement.cpython-35.pyc b/ql/ast/nodes/statements/__pycache__/block_statement.cpython-35.pyc
new file mode 100644
index 0000000..8ec170d
--- /dev/null
+++ b/ql/ast/nodes/statements/__pycache__/block_statement.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/statements/__pycache__/form_statement.cpython-35.pyc b/ql/ast/nodes/statements/__pycache__/form_statement.cpython-35.pyc
new file mode 100644
index 0000000..e10775a
--- /dev/null
+++ b/ql/ast/nodes/statements/__pycache__/form_statement.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/statements/__pycache__/if_statement.cpython-35.pyc b/ql/ast/nodes/statements/__pycache__/if_statement.cpython-35.pyc
new file mode 100644
index 0000000..e81cfc1
--- /dev/null
+++ b/ql/ast/nodes/statements/__pycache__/if_statement.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/statements/__pycache__/question_statement.cpython-35.pyc b/ql/ast/nodes/statements/__pycache__/question_statement.cpython-35.pyc
new file mode 100644
index 0000000..6b86ed9
--- /dev/null
+++ b/ql/ast/nodes/statements/__pycache__/question_statement.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/nodes/statements/block_statement.py b/ql/ast/nodes/statements/block_statement.py
new file mode 100644
index 0000000..2013c82
--- /dev/null
+++ b/ql/ast/nodes/statements/block_statement.py
@@ -0,0 +1,11 @@
+from ql.ast.nodes.base import BaseNode
+
+
+class BlockStatementNode(BaseNode):
+ def __init__(self, metadata, block):
+ super(BlockStatementNode, self).__init__(metadata)
+ self.__block = block
+
+ @property
+ def block(self):
+ return self.__block
diff --git a/ql/ast/nodes/statements/form_statement.py b/ql/ast/nodes/statements/form_statement.py
new file mode 100644
index 0000000..0030623
--- /dev/null
+++ b/ql/ast/nodes/statements/form_statement.py
@@ -0,0 +1,12 @@
+from ql.ast.nodes.statements.block_statement import BlockStatementNode
+
+
+class FormNode(BlockStatementNode):
+ def __init__(self, metadata, block, identifier):
+ super(FormNode, self).__init__(metadata, block)
+ self.__identifier = identifier
+
+ @property
+ def identifier(self):
+ return self.__identifier
+
diff --git a/ql/ast/nodes/statements/if_statement.py b/ql/ast/nodes/statements/if_statement.py
new file mode 100644
index 0000000..68845b8
--- /dev/null
+++ b/ql/ast/nodes/statements/if_statement.py
@@ -0,0 +1,11 @@
+from ql.ast.nodes.statements.block_statement import BlockStatementNode
+
+
+class IfNode(BlockStatementNode):
+ def __init__(self, metadata, block, condition):
+ super(IfNode, self).__init__(metadata, block)
+ self.__condition = condition
+
+ @property
+ def condition(self):
+ return self.__condition
diff --git a/ql/ast/nodes/statements/question_statement.py b/ql/ast/nodes/statements/question_statement.py
new file mode 100644
index 0000000..2878449
--- /dev/null
+++ b/ql/ast/nodes/statements/question_statement.py
@@ -0,0 +1,31 @@
+from ql.ast.nodes.base import BaseNode
+
+
+class QuestionNode(BaseNode):
+ def __init__(self, line_number, label, identifier, answer_type, answer, computed):
+ super(QuestionNode, self).__init__(line_number)
+ self.__label = label
+ self.__identifier = identifier
+ self.__answer_type = answer_type
+ self.__answer = answer
+ self.__computed = computed
+
+ @property
+ def label(self):
+ return self.__label
+
+ @property
+ def identifier(self):
+ return self.__identifier
+
+ @property
+ def answer_type(self):
+ return self.__answer_type
+
+ @property
+ def answer(self):
+ return self.__answer
+
+ @property
+ def computed(self):
+ return self.__computed
diff --git a/ql/ast/visitors/__pycache__/dependency_visitor.cpython-35.pyc b/ql/ast/visitors/__pycache__/dependency_visitor.cpython-35.pyc
new file mode 100644
index 0000000..8d348e6
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/dependency_visitor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/expression_evaluator.cpython-35.pyc b/ql/ast/visitors/__pycache__/expression_evaluator.cpython-35.pyc
new file mode 100644
index 0000000..29a2e9b
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/expression_evaluator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/identifier_type_visitor.cpython-35.pyc b/ql/ast/visitors/__pycache__/identifier_type_visitor.cpython-35.pyc
new file mode 100644
index 0000000..89f690d
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/identifier_type_visitor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/model_generator.cpython-35.pyc b/ql/ast/visitors/__pycache__/model_generator.cpython-35.pyc
new file mode 100644
index 0000000..9950522
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/model_generator.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/question_visitor.cpython-35.pyc b/ql/ast/visitors/__pycache__/question_visitor.cpython-35.pyc
new file mode 100644
index 0000000..ac60a13
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/question_visitor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/reference_visitor.cpython-35.pyc b/ql/ast/visitors/__pycache__/reference_visitor.cpython-35.pyc
new file mode 100644
index 0000000..e0491b9
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/reference_visitor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/__pycache__/type_visitor.cpython-35.pyc b/ql/ast/visitors/__pycache__/type_visitor.cpython-35.pyc
new file mode 100644
index 0000000..a2df3f2
--- /dev/null
+++ b/ql/ast/visitors/__pycache__/type_visitor.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/visitors/dependency_visitor.py b/ql/ast/visitors/dependency_visitor.py
new file mode 100644
index 0000000..8bb81eb
--- /dev/null
+++ b/ql/ast/visitors/dependency_visitor.py
@@ -0,0 +1,54 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.ast.nodes.expressions.variable import VariableNode
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+
+
+class DependencyVisitor:
+ def __init__(self):
+ self.__all_dependencies = []
+ self.__current_dependencies = []
+
+ @property
+ def identifier_dependencies(self):
+ return self.__all_dependencies
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ node.condition.accept(self)
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ if node.computed:
+ self.__current_dependencies = []
+ node.answer.accept(self)
+ self.__all_dependencies.append((node.identifier, self.__current_dependencies, node.metadata))
+
+ @multimethod(BinaryOperatorNode)
+ def visit(self, node):
+ node.left_expression.accept(self)
+ node.right_expression.accept(self)
+
+ @multimethod(UnaryOperatorNode)
+ def visit(self, node):
+ node.expression.accept(self)
+
+ @multimethod(VariableNode)
+ def visit(self, node):
+ self.__current_dependencies.append(node.identifier)
+
+ @multimethod(LiteralNode)
+ def visit(self, node):
+ pass
diff --git a/ql/ast/visitors/expression_evaluator.py b/ql/ast/visitors/expression_evaluator.py
new file mode 100644
index 0000000..9306d98
--- /dev/null
+++ b/ql/ast/visitors/expression_evaluator.py
@@ -0,0 +1,37 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.ast.nodes.expressions.variable import VariableNode
+from ql.types.undefined import QLUndefined
+
+
+class ExpressionEvaluator:
+ def __init__(self, form):
+ self.form = form
+ self.result = QLUndefined()
+
+ @multimethod(BinaryOperatorNode)
+ def visit(self, node):
+ node.left_expression.accept(self)
+ node.right_expression.accept(self)
+ node.evaluate()
+ self.result = node.value
+
+ @multimethod(UnaryOperatorNode)
+ def visit(self, node):
+ node.expression.accept(self)
+ node.evaluate()
+ self.result = node.value
+
+ @multimethod(LiteralNode)
+ def visit(self, node):
+ self.result = node.value
+
+ @multimethod(VariableNode)
+ def visit(self, node):
+ for question in self.form.block:
+ if node.identifier == question.identifier:
+ node.value = question.answer.value
+ self.result = node.value
diff --git a/ql/ast/visitors/identifier_type_visitor.py b/ql/ast/visitors/identifier_type_visitor.py
new file mode 100644
index 0000000..d064f5b
--- /dev/null
+++ b/ql/ast/visitors/identifier_type_visitor.py
@@ -0,0 +1,31 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+
+
+class IdentifierTypeVisitor:
+ def __init__(self):
+ self.__symbol_table = []
+
+ @property
+ def symbol_table(self):
+ return self.__symbol_table
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ self.__symbol_table.append({
+ 'identifier': node.identifier,
+ 'answer_type': node.answer_type,
+ })
diff --git a/ql/ast/visitors/model_generator.py b/ql/ast/visitors/model_generator.py
new file mode 100644
index 0000000..f2cf5d8
--- /dev/null
+++ b/ql/ast/visitors/model_generator.py
@@ -0,0 +1,39 @@
+from multimethods import multimethod
+
+from gui.model.form import FormModel
+from gui.model.question import QuestionModel
+from ql.ast.nodes.expressions.binary_operators.and_operator import AndOperatorNode
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+from ql.types.boolean import QLBoolean
+from ql.types.undefined import QLUndefined
+
+
+class ModelGenerator:
+ def __init__(self):
+ self.form = None
+ self.condition = QLBoolean.get_literal_node(True)
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ self.form = FormModel(node.identifier)
+
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ previous_condition = self.condition
+ self.condition = AndOperatorNode(None, QLBoolean, self.condition, node.condition, QLUndefined())
+
+ for child in node.block:
+ child.accept(self)
+
+ self.condition = previous_condition
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ question_model = QuestionModel(node.label, node.identifier, node.answer_type,
+ node.answer, node.computed, self.condition)
+ self.form.block.append(question_model)
diff --git a/ql/ast/visitors/question_visitor.py b/ql/ast/visitors/question_visitor.py
new file mode 100644
index 0000000..8037364
--- /dev/null
+++ b/ql/ast/visitors/question_visitor.py
@@ -0,0 +1,33 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+
+
+class QuestionVisitor:
+ def __init__(self):
+ self.__questions = []
+
+ @property
+ def questions(self):
+ return self.__questions
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ self.__questions.append({
+ 'label': node.label,
+ 'identifier': node.identifier,
+ 'answer_type': node.answer_type,
+ 'metadata': node.metadata,
+ })
diff --git a/ql/ast/visitors/reference_visitor.py b/ql/ast/visitors/reference_visitor.py
new file mode 100644
index 0000000..5cbbcc7
--- /dev/null
+++ b/ql/ast/visitors/reference_visitor.py
@@ -0,0 +1,86 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.ast.nodes.expressions.variable import VariableNode
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+
+
+class ReferenceVisitor:
+ def __init__(self):
+ self.__current_block = []
+ self.__current_scope = {}
+
+ @property
+ def identifier_scopes(self):
+ return self.__current_scope
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ self.__current_scope = {
+ 'content': [],
+ 'children': [],
+ }
+ self.__current_block = []
+
+ for child in node.block:
+ child.accept(self)
+
+ self.__current_scope['content'] = self.__current_block
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ node.condition.accept(self)
+
+ self.__current_scope['content'] += self.__current_block
+ previous_scope = self.__current_scope
+ previous_block = self.__current_block
+ self.__current_block = []
+ self.__current_scope = {
+ 'content': [],
+ 'children': [],
+ }
+
+ for child in node.block:
+ child.accept(self)
+
+ self.__current_scope['content'] = self.__current_block
+ previous_scope['children'].append(self.__current_scope)
+ self.__current_block = previous_block
+ self.__current_scope = previous_scope
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ self.__current_block.append(dict({
+ 'name': node.identifier,
+ 'type': node.answer_type,
+ 'line': node.metadata.line,
+ }))
+
+ if node.computed:
+ node.answer.accept(self)
+
+ @multimethod(BinaryOperatorNode)
+ def visit(self, node):
+ node.left_expression.accept(self)
+ node.right_expression.accept(self)
+
+ @multimethod(UnaryOperatorNode)
+ def visit(self, node):
+ node.expression.accept(self)
+
+ @multimethod(VariableNode)
+ def visit(self, node):
+ name = node.identifier
+ self.__current_block.append({
+ 'name': name,
+ 'type': [],
+ 'line': node.metadata.line,
+ })
+
+ @multimethod(LiteralNode)
+ def visit(self, node):
+ pass
diff --git a/ql/ast/visitors/type_visitor.py b/ql/ast/visitors/type_visitor.py
new file mode 100644
index 0000000..7f4ac7c
--- /dev/null
+++ b/ql/ast/visitors/type_visitor.py
@@ -0,0 +1,85 @@
+from multimethods import multimethod
+
+from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
+from ql.ast.nodes.expressions.literals.literal import LiteralNode
+from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
+from ql.ast.nodes.expressions.variable import VariableNode
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+from ql.types.boolean import QLBoolean
+from ql.types.undefined import QLUndefined
+
+
+class TypeVisitor:
+ def __init__(self, symbol_table):
+ self.__symbol_table = symbol_table
+ self.__errors = []
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ @multimethod(FormNode)
+ def visit(self, node):
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(IfNode)
+ def visit(self, node):
+ node.condition.accept(self)
+
+ if node.condition.expression_type != QLBoolean:
+ self.__errors.append('Condition does not evaluate to boolean on line {}.'
+ .format(node.metadata.line))
+
+ for child in node.block:
+ child.accept(self)
+
+ @multimethod(QuestionNode)
+ def visit(self, node):
+ if node.computed:
+ node.answer.accept(self)
+
+ result_type = node.answer.expression_type
+
+ if node.answer_type != result_type:
+ self.__errors.append('Expression not of type {} on line {}'
+ .format(node.answer_type, node.answer.metadata.line))
+
+ @multimethod(BinaryOperatorNode)
+ def visit(self, node):
+ node.left_expression.accept(self)
+ node.right_expression.accept(self)
+
+ result_type = node.get_result_type()
+
+ if result_type == QLUndefined:
+ self.__errors.append('Invalid operands: {} and {} not supported for binary operation on line {}'
+ .format(node.left_expression.expression_type,
+ node.right_expression.expression_type,
+ node.metadata.line))
+
+ node.expression_type = result_type
+
+ @multimethod(UnaryOperatorNode)
+ def visit(self, node):
+ node.expression.accept(self)
+
+ result_type = node.get_result_type()
+
+ if result_type == QLUndefined:
+ self.__errors.append('Invalid operand: {} not supported for unary operation on line {}'
+ .format(node.expression.expression_type, node.metadata.line))
+
+ node.expression_type = result_type
+
+ @multimethod(VariableNode)
+ def visit(self, node):
+ for row in self.__symbol_table:
+ if row['identifier'] == node.identifier:
+ node.expression_type = row['answer_type']
+
+ @multimethod(LiteralNode)
+ def visit(self, node):
+ pass
diff --git a/ql/parser/__pycache__/lexer.cpython-35.pyc b/ql/parser/__pycache__/lexer.cpython-35.pyc
new file mode 100644
index 0000000..f2d9220
--- /dev/null
+++ b/ql/parser/__pycache__/lexer.cpython-35.pyc
Binary files differ
diff --git a/ql/parser/__pycache__/metadata.cpython-35.pyc b/ql/parser/__pycache__/metadata.cpython-35.pyc
new file mode 100644
index 0000000..0f1f298
--- /dev/null
+++ b/ql/parser/__pycache__/metadata.cpython-35.pyc
Binary files differ
diff --git a/ql/parser/__pycache__/parser.cpython-35.pyc b/ql/parser/__pycache__/parser.cpython-35.pyc
new file mode 100644
index 0000000..6eb96b9
--- /dev/null
+++ b/ql/parser/__pycache__/parser.cpython-35.pyc
Binary files differ
diff --git a/ql/parser/__pycache__/parsetab.cpython-35.pyc b/ql/parser/__pycache__/parsetab.cpython-35.pyc
new file mode 100644
index 0000000..bd4db77
--- /dev/null
+++ b/ql/parser/__pycache__/parsetab.cpython-35.pyc
Binary files differ
diff --git a/ql/parser/lexer.py b/ql/parser/lexer.py
new file mode 100644
index 0000000..6e53f12
--- /dev/null
+++ b/ql/parser/lexer.py
@@ -0,0 +1,153 @@
+from re import findall
+
+from ply.lex import lex
+
+
+class QLLexer:
+ def __init__(self):
+ self.__errors = []
+ self.__lexer = None
+
+ @property
+ def lexer(self):
+ return self.__lexer
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ def build(self):
+ self.__lexer = lex(module=self)
+
+ def tokenize(self, data):
+ self.__errors = []
+ self.lexer.input(data)
+ token = self.lexer.token()
+ tokens = [token]
+
+ while token:
+ token = self.lexer.token()
+ tokens.append(token)
+
+ return tokens
+
+ tokens = [
+ 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'COLON',
+ 'ASSIGN',
+ 'EQUALS', 'NOT_EQUALS',
+ 'LESS_EQUALS', 'LESS_THAN', 'GREATER_EQUALS', 'GREATER_THAN',
+ 'AND', 'OR',
+ 'DOLLAR', 'RUBLE',
+ 'LEFT_BRACE', 'RIGHT_BRACE',
+ 'LEFT_BRACKET', 'RIGHT_BRACKET',
+ 'INTEGER_LITERAL', 'DECIMAL_LITERAL',
+ 'TRUE', 'FALSE',
+ 'DATE_LITERAL',
+ 'STRING_LITERAL',
+ 'IDENTIFIER',
+ ]
+
+ reserved_keywords = {
+ 'form': 'FORM',
+ 'if': 'IF',
+ 'not': 'NOT',
+
+ # Types
+ 'boolean': 'BOOLEAN',
+ 'date': 'DATE',
+ 'decimal': 'DECIMAL',
+ 'integer': 'INTEGER',
+ 'money': 'MONEY',
+ 'string': 'STRING',
+ }
+
+ tokens += list(reserved_keywords.values())
+
+ # Regular expression rules for simple tokens
+ t_ignore = ' \t'
+
+ t_PLUS = r'\+'
+ t_MINUS = r'-'
+ t_TIMES = r'\*'
+ t_DIVIDE = r'/'
+ t_COLON = r':'
+ t_ASSIGN = r'='
+
+ t_LESS_EQUALS = r'<='
+ t_LESS_THAN = r'<'
+ t_GREATER_EQUALS = r'>='
+ t_GREATER_THAN = r'>'
+ t_EQUALS = r'=='
+ t_NOT_EQUALS = r'!='
+ t_AND = r'&&'
+ t_OR = r'\|\|'
+
+ t_DOLLAR = r'\$'
+ t_RUBLE = r'\₽'
+
+ t_LEFT_BRACE = r'\{'
+ t_RIGHT_BRACE = r'\}'
+
+ t_LEFT_BRACKET = r'\('
+ t_RIGHT_BRACKET = r'\)'
+
+ # Literals
+ @staticmethod
+ def t_FALSE(token):
+ r'False'
+ token.value = False
+ return token
+
+ @staticmethod
+ def t_TRUE(token):
+ r'True'
+ token.value = True
+ return token
+
+ def t_DATE_LITERAL(self, token):
+ r'date\(\s*\d{1,2}\s*,\s*\d{1,2}\s*,\s*\d{1,4}\s*\)'
+
+ try:
+ token.value = findall(r'\d\d*', token.value)
+ return token
+ except SyntaxError:
+ self.errors.append('Invalid date.')
+
+ @staticmethod
+ def t_DECIMAL_LITERAL(token):
+ r'\d+[.]\d+'
+ token.value = token.value
+ return token
+
+ @staticmethod
+ def t_INTEGER_LITERAL(token):
+ r'\d+'
+ token.value = token.value
+ return token
+
+ @staticmethod
+ def t_STRING_LITERAL(token):
+ r'\"(.+?)\"'
+ token.value = token.value[1:-1]
+ return token
+
+ # Other
+ def t_IDENTIFIER(self, token):
+ r'[a-z][a-zA-Z_0-9]*'
+ token.type = self.reserved_keywords.get(token.value, 'IDENTIFIER')
+ return token
+
+ @staticmethod
+ def t_comment(token):
+ r'//.*'
+ pass
+
+ @staticmethod
+ def t_newline(token):
+ r'\n+'
+ token.lexer.lineno += len(token.value)
+
+ # Error handling
+ def t_error(self, token):
+ self.errors.append("Illegal character '%s'" % token.value[0])
+ token.lexer.skip(1)
diff --git a/ql/parser/metadata.py b/ql/parser/metadata.py
new file mode 100644
index 0000000..618b4ba
--- /dev/null
+++ b/ql/parser/metadata.py
@@ -0,0 +1,7 @@
+class Metadata:
+ def __init__(self, line):
+ self.__line = line
+
+ @property
+ def line(self):
+ return self.__line
diff --git a/ql/parser/parser.out b/ql/parser/parser.out
new file mode 100644
index 0000000..e1a1452
--- /dev/null
+++ b/ql/parser/parser.out
@@ -0,0 +1,2214 @@
+Created by PLY version 3.11 (http://www.dabeaz.com/ply)
+
+Grammar
+
+Rule 0 S' -> form
+Rule 1 form -> FORM IDENTIFIER block
+Rule 2 block -> LEFT_BRACE statements RIGHT_BRACE
+Rule 3 statements -> statement statements
+Rule 4 statements -> statement
+Rule 5 statement -> if
+Rule 6 statement -> question
+Rule 7 question -> STRING_LITERAL IDENTIFIER COLON type
+Rule 8 question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression
+Rule 9 if -> IF condition block
+Rule 10 condition -> LEFT_BRACKET expression RIGHT_BRACKET
+Rule 11 expression -> LEFT_BRACKET expression RIGHT_BRACKET
+Rule 12 expression -> IDENTIFIER
+Rule 13 expression -> NOT expression
+Rule 14 expression -> MINUS expression
+Rule 15 expression -> expression AND expression
+Rule 16 expression -> expression OR expression
+Rule 17 expression -> expression PLUS expression
+Rule 18 expression -> expression MINUS expression
+Rule 19 expression -> expression TIMES expression
+Rule 20 expression -> expression DIVIDE expression
+Rule 21 expression -> expression EQUALS expression
+Rule 22 expression -> expression NOT_EQUALS expression
+Rule 23 expression -> expression LESS_EQUALS expression
+Rule 24 expression -> expression LESS_THAN expression
+Rule 25 expression -> expression GREATER_EQUALS expression
+Rule 26 expression -> expression GREATER_THAN expression
+Rule 27 expression -> FALSE
+Rule 28 expression -> TRUE
+Rule 29 expression -> DATE_LITERAL
+Rule 30 expression -> INTEGER_LITERAL
+Rule 31 expression -> DECIMAL_LITERAL
+Rule 32 expression -> currency DECIMAL_LITERAL
+Rule 33 expression -> currency INTEGER_LITERAL
+Rule 34 expression -> STRING_LITERAL
+Rule 35 currency -> DOLLAR
+Rule 36 currency -> RUBLE
+Rule 37 type -> BOOLEAN
+Rule 38 type -> DECIMAL
+Rule 39 type -> STRING
+Rule 40 type -> DATE
+Rule 41 type -> MONEY
+Rule 42 type -> INTEGER
+Rule 43 form -> FORM LEFT_BRACE
+Rule 44 form -> FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE
+Rule 45 statement -> IF condition LEFT_BRACE RIGHT_BRACE
+Rule 46 condition -> LEFT_BRACKET RIGHT_BRACKET
+
+Terminals, with rules where they appear
+
+AND : 15
+ASSIGN : 8
+BOOLEAN : 37
+COLON : 7 8
+DATE : 40
+DATE_LITERAL : 29
+DECIMAL : 38
+DECIMAL_LITERAL : 31 32
+DIVIDE : 20
+DOLLAR : 35
+EQUALS : 21
+FALSE : 27
+FORM : 1 43 44
+GREATER_EQUALS : 25
+GREATER_THAN : 26
+IDENTIFIER : 1 7 8 12 44
+IF : 9 45
+INTEGER : 42
+INTEGER_LITERAL : 30 33
+LEFT_BRACE : 2 43 44 45
+LEFT_BRACKET : 10 11 46
+LESS_EQUALS : 23
+LESS_THAN : 24
+MINUS : 14 18
+MONEY : 41
+NOT : 13
+NOT_EQUALS : 22
+OR : 16
+PLUS : 17
+RIGHT_BRACE : 2 44 45
+RIGHT_BRACKET : 10 11 46
+RUBLE : 36
+STRING : 39
+STRING_LITERAL : 7 8 34
+TIMES : 19
+TRUE : 28
+error :
+
+Nonterminals, with rules where they appear
+
+block : 1 9
+condition : 9 45
+currency : 32 33
+expression : 8 10 11 13 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26
+form : 0
+if : 5
+question : 6
+statement : 3 4
+statements : 2 3
+type : 7 8
+
+Parsing method: LALR
+
+state 0
+
+ (0) S' -> . form
+ (1) form -> . FORM IDENTIFIER block
+ (43) form -> . FORM LEFT_BRACE
+ (44) form -> . FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE
+
+ FORM shift and go to state 1
+
+ form shift and go to state 2
+
+state 1
+
+ (1) form -> FORM . IDENTIFIER block
+ (43) form -> FORM . LEFT_BRACE
+ (44) form -> FORM . IDENTIFIER LEFT_BRACE RIGHT_BRACE
+
+ IDENTIFIER shift and go to state 3
+ LEFT_BRACE shift and go to state 4
+
+
+state 2
+
+ (0) S' -> form .
+
+
+
+state 3
+
+ (1) form -> FORM IDENTIFIER . block
+ (44) form -> FORM IDENTIFIER . LEFT_BRACE RIGHT_BRACE
+ (2) block -> . LEFT_BRACE statements RIGHT_BRACE
+
+ LEFT_BRACE shift and go to state 5
+
+ block shift and go to state 6
+
+state 4
+
+ (43) form -> FORM LEFT_BRACE .
+
+ $end reduce using rule 43 (form -> FORM LEFT_BRACE .)
+
+
+state 5
+
+ (44) form -> FORM IDENTIFIER LEFT_BRACE . RIGHT_BRACE
+ (2) block -> LEFT_BRACE . statements RIGHT_BRACE
+ (3) statements -> . statement statements
+ (4) statements -> . statement
+ (5) statement -> . if
+ (6) statement -> . question
+ (45) statement -> . IF condition LEFT_BRACE RIGHT_BRACE
+ (9) if -> . IF condition block
+ (7) question -> . STRING_LITERAL IDENTIFIER COLON type
+ (8) question -> . STRING_LITERAL IDENTIFIER COLON type ASSIGN expression
+
+ RIGHT_BRACE shift and go to state 13
+ IF shift and go to state 11
+ STRING_LITERAL shift and go to state 12
+
+ if shift and go to state 7
+ question shift and go to state 8
+ statements shift and go to state 9
+ statement shift and go to state 10
+
+state 6
+
+ (1) form -> FORM IDENTIFIER block .
+
+ $end reduce using rule 1 (form -> FORM IDENTIFIER block .)
+
+
+state 7
+
+ (5) statement -> if .
+
+ IF reduce using rule 5 (statement -> if .)
+ STRING_LITERAL reduce using rule 5 (statement -> if .)
+ RIGHT_BRACE reduce using rule 5 (statement -> if .)
+
+
+state 8
+
+ (6) statement -> question .
+
+ IF reduce using rule 6 (statement -> question .)
+ STRING_LITERAL reduce using rule 6 (statement -> question .)
+ RIGHT_BRACE reduce using rule 6 (statement -> question .)
+
+
+state 9
+
+ (2) block -> LEFT_BRACE statements . RIGHT_BRACE
+
+ RIGHT_BRACE shift and go to state 14
+
+
+state 10
+
+ (3) statements -> statement . statements
+ (4) statements -> statement .
+ (3) statements -> . statement statements
+ (4) statements -> . statement
+ (5) statement -> . if
+ (6) statement -> . question
+ (45) statement -> . IF condition LEFT_BRACE RIGHT_BRACE
+ (9) if -> . IF condition block
+ (7) question -> . STRING_LITERAL IDENTIFIER COLON type
+ (8) question -> . STRING_LITERAL IDENTIFIER COLON type ASSIGN expression
+
+ RIGHT_BRACE reduce using rule 4 (statements -> statement .)
+ IF shift and go to state 11
+ STRING_LITERAL shift and go to state 12
+
+ if shift and go to state 7
+ question shift and go to state 8
+ statements shift and go to state 15
+ statement shift and go to state 10
+
+state 11
+
+ (45) statement -> IF . condition LEFT_BRACE RIGHT_BRACE
+ (9) if -> IF . condition block
+ (10) condition -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (46) condition -> . LEFT_BRACKET RIGHT_BRACKET
+
+ LEFT_BRACKET shift and go to state 17
+
+ condition shift and go to state 16
+
+state 12
+
+ (7) question -> STRING_LITERAL . IDENTIFIER COLON type
+ (8) question -> STRING_LITERAL . IDENTIFIER COLON type ASSIGN expression
+
+ IDENTIFIER shift and go to state 18
+
+
+state 13
+
+ (44) form -> FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE .
+
+ $end reduce using rule 44 (form -> FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE .)
+
+
+state 14
+
+ (2) block -> LEFT_BRACE statements RIGHT_BRACE .
+
+ IF reduce using rule 2 (block -> LEFT_BRACE statements RIGHT_BRACE .)
+ STRING_LITERAL reduce using rule 2 (block -> LEFT_BRACE statements RIGHT_BRACE .)
+ RIGHT_BRACE reduce using rule 2 (block -> LEFT_BRACE statements RIGHT_BRACE .)
+ $end reduce using rule 2 (block -> LEFT_BRACE statements RIGHT_BRACE .)
+
+
+state 15
+
+ (3) statements -> statement statements .
+
+ RIGHT_BRACE reduce using rule 3 (statements -> statement statements .)
+
+
+state 16
+
+ (45) statement -> IF condition . LEFT_BRACE RIGHT_BRACE
+ (9) if -> IF condition . block
+ (2) block -> . LEFT_BRACE statements RIGHT_BRACE
+
+ LEFT_BRACE shift and go to state 19
+
+ block shift and go to state 20
+
+state 17
+
+ (10) condition -> LEFT_BRACKET . expression RIGHT_BRACKET
+ (46) condition -> LEFT_BRACKET . RIGHT_BRACKET
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ RIGHT_BRACKET shift and go to state 21
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 33
+
+state 18
+
+ (7) question -> STRING_LITERAL IDENTIFIER . COLON type
+ (8) question -> STRING_LITERAL IDENTIFIER . COLON type ASSIGN expression
+
+ COLON shift and go to state 36
+
+
+state 19
+
+ (45) statement -> IF condition LEFT_BRACE . RIGHT_BRACE
+ (2) block -> LEFT_BRACE . statements RIGHT_BRACE
+ (3) statements -> . statement statements
+ (4) statements -> . statement
+ (5) statement -> . if
+ (6) statement -> . question
+ (45) statement -> . IF condition LEFT_BRACE RIGHT_BRACE
+ (9) if -> . IF condition block
+ (7) question -> . STRING_LITERAL IDENTIFIER COLON type
+ (8) question -> . STRING_LITERAL IDENTIFIER COLON type ASSIGN expression
+
+ RIGHT_BRACE shift and go to state 37
+ IF shift and go to state 11
+ STRING_LITERAL shift and go to state 12
+
+ if shift and go to state 7
+ question shift and go to state 8
+ statements shift and go to state 9
+ statement shift and go to state 10
+
+state 20
+
+ (9) if -> IF condition block .
+
+ IF reduce using rule 9 (if -> IF condition block .)
+ STRING_LITERAL reduce using rule 9 (if -> IF condition block .)
+ RIGHT_BRACE reduce using rule 9 (if -> IF condition block .)
+
+
+state 21
+
+ (46) condition -> LEFT_BRACKET RIGHT_BRACKET .
+
+ LEFT_BRACE reduce using rule 46 (condition -> LEFT_BRACKET RIGHT_BRACKET .)
+
+
+state 22
+
+ (32) expression -> currency . DECIMAL_LITERAL
+ (33) expression -> currency . INTEGER_LITERAL
+
+ DECIMAL_LITERAL shift and go to state 38
+ INTEGER_LITERAL shift and go to state 39
+
+
+state 23
+
+ (36) currency -> RUBLE .
+
+ DECIMAL_LITERAL reduce using rule 36 (currency -> RUBLE .)
+ INTEGER_LITERAL reduce using rule 36 (currency -> RUBLE .)
+
+
+state 24
+
+ (29) expression -> DATE_LITERAL .
+
+ AND reduce using rule 29 (expression -> DATE_LITERAL .)
+ OR reduce using rule 29 (expression -> DATE_LITERAL .)
+ PLUS reduce using rule 29 (expression -> DATE_LITERAL .)
+ MINUS reduce using rule 29 (expression -> DATE_LITERAL .)
+ TIMES reduce using rule 29 (expression -> DATE_LITERAL .)
+ DIVIDE reduce using rule 29 (expression -> DATE_LITERAL .)
+ EQUALS reduce using rule 29 (expression -> DATE_LITERAL .)
+ NOT_EQUALS reduce using rule 29 (expression -> DATE_LITERAL .)
+ LESS_EQUALS reduce using rule 29 (expression -> DATE_LITERAL .)
+ LESS_THAN reduce using rule 29 (expression -> DATE_LITERAL .)
+ GREATER_EQUALS reduce using rule 29 (expression -> DATE_LITERAL .)
+ GREATER_THAN reduce using rule 29 (expression -> DATE_LITERAL .)
+ IF reduce using rule 29 (expression -> DATE_LITERAL .)
+ STRING_LITERAL reduce using rule 29 (expression -> DATE_LITERAL .)
+ RIGHT_BRACE reduce using rule 29 (expression -> DATE_LITERAL .)
+ RIGHT_BRACKET reduce using rule 29 (expression -> DATE_LITERAL .)
+
+
+state 25
+
+ (14) expression -> MINUS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 40
+
+state 26
+
+ (30) expression -> INTEGER_LITERAL .
+
+ AND reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ OR reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ PLUS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ MINUS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ TIMES reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ DIVIDE reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ EQUALS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ NOT_EQUALS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ LESS_EQUALS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ LESS_THAN reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ GREATER_EQUALS reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ GREATER_THAN reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ IF reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ STRING_LITERAL reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ RIGHT_BRACE reduce using rule 30 (expression -> INTEGER_LITERAL .)
+ RIGHT_BRACKET reduce using rule 30 (expression -> INTEGER_LITERAL .)
+
+
+state 27
+
+ (13) expression -> NOT . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 41
+
+state 28
+
+ (34) expression -> STRING_LITERAL .
+
+ AND reduce using rule 34 (expression -> STRING_LITERAL .)
+ OR reduce using rule 34 (expression -> STRING_LITERAL .)
+ PLUS reduce using rule 34 (expression -> STRING_LITERAL .)
+ MINUS reduce using rule 34 (expression -> STRING_LITERAL .)
+ TIMES reduce using rule 34 (expression -> STRING_LITERAL .)
+ DIVIDE reduce using rule 34 (expression -> STRING_LITERAL .)
+ EQUALS reduce using rule 34 (expression -> STRING_LITERAL .)
+ NOT_EQUALS reduce using rule 34 (expression -> STRING_LITERAL .)
+ LESS_EQUALS reduce using rule 34 (expression -> STRING_LITERAL .)
+ LESS_THAN reduce using rule 34 (expression -> STRING_LITERAL .)
+ GREATER_EQUALS reduce using rule 34 (expression -> STRING_LITERAL .)
+ GREATER_THAN reduce using rule 34 (expression -> STRING_LITERAL .)
+ IF reduce using rule 34 (expression -> STRING_LITERAL .)
+ STRING_LITERAL reduce using rule 34 (expression -> STRING_LITERAL .)
+ RIGHT_BRACE reduce using rule 34 (expression -> STRING_LITERAL .)
+ RIGHT_BRACKET reduce using rule 34 (expression -> STRING_LITERAL .)
+
+
+state 29
+
+ (35) currency -> DOLLAR .
+
+ DECIMAL_LITERAL reduce using rule 35 (currency -> DOLLAR .)
+ INTEGER_LITERAL reduce using rule 35 (currency -> DOLLAR .)
+
+
+state 30
+
+ (11) expression -> LEFT_BRACKET . expression RIGHT_BRACKET
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 42
+
+state 31
+
+ (31) expression -> DECIMAL_LITERAL .
+
+ AND reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ OR reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ PLUS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ MINUS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ TIMES reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ DIVIDE reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ EQUALS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ NOT_EQUALS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ LESS_EQUALS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ LESS_THAN reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ GREATER_EQUALS reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ GREATER_THAN reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ IF reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ STRING_LITERAL reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ RIGHT_BRACE reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+ RIGHT_BRACKET reduce using rule 31 (expression -> DECIMAL_LITERAL .)
+
+
+state 32
+
+ (28) expression -> TRUE .
+
+ AND reduce using rule 28 (expression -> TRUE .)
+ OR reduce using rule 28 (expression -> TRUE .)
+ PLUS reduce using rule 28 (expression -> TRUE .)
+ MINUS reduce using rule 28 (expression -> TRUE .)
+ TIMES reduce using rule 28 (expression -> TRUE .)
+ DIVIDE reduce using rule 28 (expression -> TRUE .)
+ EQUALS reduce using rule 28 (expression -> TRUE .)
+ NOT_EQUALS reduce using rule 28 (expression -> TRUE .)
+ LESS_EQUALS reduce using rule 28 (expression -> TRUE .)
+ LESS_THAN reduce using rule 28 (expression -> TRUE .)
+ GREATER_EQUALS reduce using rule 28 (expression -> TRUE .)
+ GREATER_THAN reduce using rule 28 (expression -> TRUE .)
+ IF reduce using rule 28 (expression -> TRUE .)
+ STRING_LITERAL reduce using rule 28 (expression -> TRUE .)
+ RIGHT_BRACE reduce using rule 28 (expression -> TRUE .)
+ RIGHT_BRACKET reduce using rule 28 (expression -> TRUE .)
+
+
+state 33
+
+ (10) condition -> LEFT_BRACKET expression . RIGHT_BRACKET
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ RIGHT_BRACKET shift and go to state 43
+ AND shift and go to state 52
+ OR shift and go to state 50
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ EQUALS shift and go to state 46
+ NOT_EQUALS shift and go to state 45
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+
+state 34
+
+ (12) expression -> IDENTIFIER .
+
+ AND reduce using rule 12 (expression -> IDENTIFIER .)
+ OR reduce using rule 12 (expression -> IDENTIFIER .)
+ PLUS reduce using rule 12 (expression -> IDENTIFIER .)
+ MINUS reduce using rule 12 (expression -> IDENTIFIER .)
+ TIMES reduce using rule 12 (expression -> IDENTIFIER .)
+ DIVIDE reduce using rule 12 (expression -> IDENTIFIER .)
+ EQUALS reduce using rule 12 (expression -> IDENTIFIER .)
+ NOT_EQUALS reduce using rule 12 (expression -> IDENTIFIER .)
+ LESS_EQUALS reduce using rule 12 (expression -> IDENTIFIER .)
+ LESS_THAN reduce using rule 12 (expression -> IDENTIFIER .)
+ GREATER_EQUALS reduce using rule 12 (expression -> IDENTIFIER .)
+ GREATER_THAN reduce using rule 12 (expression -> IDENTIFIER .)
+ IF reduce using rule 12 (expression -> IDENTIFIER .)
+ STRING_LITERAL reduce using rule 12 (expression -> IDENTIFIER .)
+ RIGHT_BRACE reduce using rule 12 (expression -> IDENTIFIER .)
+ RIGHT_BRACKET reduce using rule 12 (expression -> IDENTIFIER .)
+
+
+state 35
+
+ (27) expression -> FALSE .
+
+ AND reduce using rule 27 (expression -> FALSE .)
+ OR reduce using rule 27 (expression -> FALSE .)
+ PLUS reduce using rule 27 (expression -> FALSE .)
+ MINUS reduce using rule 27 (expression -> FALSE .)
+ TIMES reduce using rule 27 (expression -> FALSE .)
+ DIVIDE reduce using rule 27 (expression -> FALSE .)
+ EQUALS reduce using rule 27 (expression -> FALSE .)
+ NOT_EQUALS reduce using rule 27 (expression -> FALSE .)
+ LESS_EQUALS reduce using rule 27 (expression -> FALSE .)
+ LESS_THAN reduce using rule 27 (expression -> FALSE .)
+ GREATER_EQUALS reduce using rule 27 (expression -> FALSE .)
+ GREATER_THAN reduce using rule 27 (expression -> FALSE .)
+ IF reduce using rule 27 (expression -> FALSE .)
+ STRING_LITERAL reduce using rule 27 (expression -> FALSE .)
+ RIGHT_BRACE reduce using rule 27 (expression -> FALSE .)
+ RIGHT_BRACKET reduce using rule 27 (expression -> FALSE .)
+
+
+state 36
+
+ (7) question -> STRING_LITERAL IDENTIFIER COLON . type
+ (8) question -> STRING_LITERAL IDENTIFIER COLON . type ASSIGN expression
+ (37) type -> . BOOLEAN
+ (38) type -> . DECIMAL
+ (39) type -> . STRING
+ (40) type -> . DATE
+ (41) type -> . MONEY
+ (42) type -> . INTEGER
+
+ BOOLEAN shift and go to state 62
+ DECIMAL shift and go to state 57
+ STRING shift and go to state 58
+ DATE shift and go to state 56
+ MONEY shift and go to state 60
+ INTEGER shift and go to state 61
+
+ type shift and go to state 59
+
+state 37
+
+ (45) statement -> IF condition LEFT_BRACE RIGHT_BRACE .
+
+ IF reduce using rule 45 (statement -> IF condition LEFT_BRACE RIGHT_BRACE .)
+ STRING_LITERAL reduce using rule 45 (statement -> IF condition LEFT_BRACE RIGHT_BRACE .)
+ RIGHT_BRACE reduce using rule 45 (statement -> IF condition LEFT_BRACE RIGHT_BRACE .)
+
+
+state 38
+
+ (32) expression -> currency DECIMAL_LITERAL .
+
+ AND reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ OR reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ PLUS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ MINUS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ TIMES reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ DIVIDE reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ EQUALS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ NOT_EQUALS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ LESS_EQUALS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ LESS_THAN reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ GREATER_EQUALS reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ GREATER_THAN reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ IF reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ STRING_LITERAL reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ RIGHT_BRACE reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+ RIGHT_BRACKET reduce using rule 32 (expression -> currency DECIMAL_LITERAL .)
+
+
+state 39
+
+ (33) expression -> currency INTEGER_LITERAL .
+
+ AND reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ OR reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ PLUS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ MINUS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ TIMES reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ DIVIDE reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ EQUALS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ NOT_EQUALS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ LESS_EQUALS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ LESS_THAN reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ GREATER_EQUALS reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ GREATER_THAN reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ IF reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ STRING_LITERAL reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ RIGHT_BRACE reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+ RIGHT_BRACKET reduce using rule 33 (expression -> currency INTEGER_LITERAL .)
+
+
+state 40
+
+ (14) expression -> MINUS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 14 (expression -> MINUS expression .)
+ OR reduce using rule 14 (expression -> MINUS expression .)
+ PLUS reduce using rule 14 (expression -> MINUS expression .)
+ MINUS reduce using rule 14 (expression -> MINUS expression .)
+ EQUALS reduce using rule 14 (expression -> MINUS expression .)
+ NOT_EQUALS reduce using rule 14 (expression -> MINUS expression .)
+ LESS_EQUALS reduce using rule 14 (expression -> MINUS expression .)
+ LESS_THAN reduce using rule 14 (expression -> MINUS expression .)
+ GREATER_EQUALS reduce using rule 14 (expression -> MINUS expression .)
+ GREATER_THAN reduce using rule 14 (expression -> MINUS expression .)
+ IF reduce using rule 14 (expression -> MINUS expression .)
+ STRING_LITERAL reduce using rule 14 (expression -> MINUS expression .)
+ RIGHT_BRACE reduce using rule 14 (expression -> MINUS expression .)
+ RIGHT_BRACKET reduce using rule 14 (expression -> MINUS expression .)
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! TIMES [ reduce using rule 14 (expression -> MINUS expression .) ]
+ ! DIVIDE [ reduce using rule 14 (expression -> MINUS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 41
+
+ (13) expression -> NOT expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 13 (expression -> NOT expression .)
+ OR reduce using rule 13 (expression -> NOT expression .)
+ PLUS reduce using rule 13 (expression -> NOT expression .)
+ MINUS reduce using rule 13 (expression -> NOT expression .)
+ TIMES reduce using rule 13 (expression -> NOT expression .)
+ DIVIDE reduce using rule 13 (expression -> NOT expression .)
+ EQUALS reduce using rule 13 (expression -> NOT expression .)
+ NOT_EQUALS reduce using rule 13 (expression -> NOT expression .)
+ LESS_EQUALS reduce using rule 13 (expression -> NOT expression .)
+ LESS_THAN reduce using rule 13 (expression -> NOT expression .)
+ GREATER_EQUALS reduce using rule 13 (expression -> NOT expression .)
+ GREATER_THAN reduce using rule 13 (expression -> NOT expression .)
+ IF reduce using rule 13 (expression -> NOT expression .)
+ STRING_LITERAL reduce using rule 13 (expression -> NOT expression .)
+ RIGHT_BRACE reduce using rule 13 (expression -> NOT expression .)
+ RIGHT_BRACKET reduce using rule 13 (expression -> NOT expression .)
+
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! TIMES [ shift and go to state 49 ]
+ ! DIVIDE [ shift and go to state 51 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 42
+
+ (11) expression -> LEFT_BRACKET expression . RIGHT_BRACKET
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ RIGHT_BRACKET shift and go to state 63
+ AND shift and go to state 52
+ OR shift and go to state 50
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ EQUALS shift and go to state 46
+ NOT_EQUALS shift and go to state 45
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+
+state 43
+
+ (10) condition -> LEFT_BRACKET expression RIGHT_BRACKET .
+
+ LEFT_BRACE reduce using rule 10 (condition -> LEFT_BRACKET expression RIGHT_BRACKET .)
+
+
+state 44
+
+ (17) expression -> expression PLUS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 64
+
+state 45
+
+ (22) expression -> expression NOT_EQUALS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 65
+
+state 46
+
+ (21) expression -> expression EQUALS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 66
+
+state 47
+
+ (24) expression -> expression LESS_THAN . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 67
+
+state 48
+
+ (18) expression -> expression MINUS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 68
+
+state 49
+
+ (19) expression -> expression TIMES . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 69
+
+state 50
+
+ (16) expression -> expression OR . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 70
+
+state 51
+
+ (20) expression -> expression DIVIDE . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 71
+
+state 52
+
+ (15) expression -> expression AND . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 72
+
+state 53
+
+ (26) expression -> expression GREATER_THAN . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 73
+
+state 54
+
+ (23) expression -> expression LESS_EQUALS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 74
+
+state 55
+
+ (25) expression -> expression GREATER_EQUALS . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ currency shift and go to state 22
+ expression shift and go to state 75
+
+state 56
+
+ (40) type -> DATE .
+
+ ASSIGN reduce using rule 40 (type -> DATE .)
+ IF reduce using rule 40 (type -> DATE .)
+ STRING_LITERAL reduce using rule 40 (type -> DATE .)
+ RIGHT_BRACE reduce using rule 40 (type -> DATE .)
+
+
+state 57
+
+ (38) type -> DECIMAL .
+
+ ASSIGN reduce using rule 38 (type -> DECIMAL .)
+ IF reduce using rule 38 (type -> DECIMAL .)
+ STRING_LITERAL reduce using rule 38 (type -> DECIMAL .)
+ RIGHT_BRACE reduce using rule 38 (type -> DECIMAL .)
+
+
+state 58
+
+ (39) type -> STRING .
+
+ ASSIGN reduce using rule 39 (type -> STRING .)
+ IF reduce using rule 39 (type -> STRING .)
+ STRING_LITERAL reduce using rule 39 (type -> STRING .)
+ RIGHT_BRACE reduce using rule 39 (type -> STRING .)
+
+
+state 59
+
+ (7) question -> STRING_LITERAL IDENTIFIER COLON type .
+ (8) question -> STRING_LITERAL IDENTIFIER COLON type . ASSIGN expression
+
+ IF reduce using rule 7 (question -> STRING_LITERAL IDENTIFIER COLON type .)
+ STRING_LITERAL reduce using rule 7 (question -> STRING_LITERAL IDENTIFIER COLON type .)
+ RIGHT_BRACE reduce using rule 7 (question -> STRING_LITERAL IDENTIFIER COLON type .)
+ ASSIGN shift and go to state 76
+
+
+state 60
+
+ (41) type -> MONEY .
+
+ ASSIGN reduce using rule 41 (type -> MONEY .)
+ IF reduce using rule 41 (type -> MONEY .)
+ STRING_LITERAL reduce using rule 41 (type -> MONEY .)
+ RIGHT_BRACE reduce using rule 41 (type -> MONEY .)
+
+
+state 61
+
+ (42) type -> INTEGER .
+
+ ASSIGN reduce using rule 42 (type -> INTEGER .)
+ IF reduce using rule 42 (type -> INTEGER .)
+ STRING_LITERAL reduce using rule 42 (type -> INTEGER .)
+ RIGHT_BRACE reduce using rule 42 (type -> INTEGER .)
+
+
+state 62
+
+ (37) type -> BOOLEAN .
+
+ ASSIGN reduce using rule 37 (type -> BOOLEAN .)
+ IF reduce using rule 37 (type -> BOOLEAN .)
+ STRING_LITERAL reduce using rule 37 (type -> BOOLEAN .)
+ RIGHT_BRACE reduce using rule 37 (type -> BOOLEAN .)
+
+
+state 63
+
+ (11) expression -> LEFT_BRACKET expression RIGHT_BRACKET .
+
+ AND reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ OR reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ PLUS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ MINUS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ TIMES reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ DIVIDE reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ EQUALS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ NOT_EQUALS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ LESS_EQUALS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ LESS_THAN reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ GREATER_EQUALS reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ GREATER_THAN reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ IF reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ STRING_LITERAL reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ RIGHT_BRACE reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+ RIGHT_BRACKET reduce using rule 11 (expression -> LEFT_BRACKET expression RIGHT_BRACKET .)
+
+
+state 64
+
+ (17) expression -> expression PLUS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 17 (expression -> expression PLUS expression .)
+ OR reduce using rule 17 (expression -> expression PLUS expression .)
+ PLUS reduce using rule 17 (expression -> expression PLUS expression .)
+ MINUS reduce using rule 17 (expression -> expression PLUS expression .)
+ EQUALS reduce using rule 17 (expression -> expression PLUS expression .)
+ NOT_EQUALS reduce using rule 17 (expression -> expression PLUS expression .)
+ LESS_EQUALS reduce using rule 17 (expression -> expression PLUS expression .)
+ LESS_THAN reduce using rule 17 (expression -> expression PLUS expression .)
+ GREATER_EQUALS reduce using rule 17 (expression -> expression PLUS expression .)
+ GREATER_THAN reduce using rule 17 (expression -> expression PLUS expression .)
+ IF reduce using rule 17 (expression -> expression PLUS expression .)
+ STRING_LITERAL reduce using rule 17 (expression -> expression PLUS expression .)
+ RIGHT_BRACE reduce using rule 17 (expression -> expression PLUS expression .)
+ RIGHT_BRACKET reduce using rule 17 (expression -> expression PLUS expression .)
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! TIMES [ reduce using rule 17 (expression -> expression PLUS expression .) ]
+ ! DIVIDE [ reduce using rule 17 (expression -> expression PLUS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 65
+
+ (22) expression -> expression NOT_EQUALS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ OR reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ EQUALS reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ NOT_EQUALS reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ IF reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ STRING_LITERAL reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ RIGHT_BRACE reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ RIGHT_BRACKET reduce using rule 22 (expression -> expression NOT_EQUALS expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+ ! PLUS [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! MINUS [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! TIMES [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! DIVIDE [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! LESS_EQUALS [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! LESS_THAN [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! GREATER_EQUALS [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! GREATER_THAN [ reduce using rule 22 (expression -> expression NOT_EQUALS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+
+
+state 66
+
+ (21) expression -> expression EQUALS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 21 (expression -> expression EQUALS expression .)
+ OR reduce using rule 21 (expression -> expression EQUALS expression .)
+ EQUALS reduce using rule 21 (expression -> expression EQUALS expression .)
+ NOT_EQUALS reduce using rule 21 (expression -> expression EQUALS expression .)
+ IF reduce using rule 21 (expression -> expression EQUALS expression .)
+ STRING_LITERAL reduce using rule 21 (expression -> expression EQUALS expression .)
+ RIGHT_BRACE reduce using rule 21 (expression -> expression EQUALS expression .)
+ RIGHT_BRACKET reduce using rule 21 (expression -> expression EQUALS expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+ ! PLUS [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! MINUS [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! TIMES [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! DIVIDE [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! LESS_EQUALS [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! LESS_THAN [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! GREATER_EQUALS [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! GREATER_THAN [ reduce using rule 21 (expression -> expression EQUALS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+
+
+state 67
+
+ (24) expression -> expression LESS_THAN expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ OR reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ EQUALS reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ NOT_EQUALS reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ LESS_EQUALS reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ LESS_THAN reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ GREATER_EQUALS reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ GREATER_THAN reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ IF reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ STRING_LITERAL reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ RIGHT_BRACE reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ RIGHT_BRACKET reduce using rule 24 (expression -> expression LESS_THAN expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! PLUS [ reduce using rule 24 (expression -> expression LESS_THAN expression .) ]
+ ! MINUS [ reduce using rule 24 (expression -> expression LESS_THAN expression .) ]
+ ! TIMES [ reduce using rule 24 (expression -> expression LESS_THAN expression .) ]
+ ! DIVIDE [ reduce using rule 24 (expression -> expression LESS_THAN expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 68
+
+ (18) expression -> expression MINUS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 18 (expression -> expression MINUS expression .)
+ OR reduce using rule 18 (expression -> expression MINUS expression .)
+ PLUS reduce using rule 18 (expression -> expression MINUS expression .)
+ MINUS reduce using rule 18 (expression -> expression MINUS expression .)
+ EQUALS reduce using rule 18 (expression -> expression MINUS expression .)
+ NOT_EQUALS reduce using rule 18 (expression -> expression MINUS expression .)
+ LESS_EQUALS reduce using rule 18 (expression -> expression MINUS expression .)
+ LESS_THAN reduce using rule 18 (expression -> expression MINUS expression .)
+ GREATER_EQUALS reduce using rule 18 (expression -> expression MINUS expression .)
+ GREATER_THAN reduce using rule 18 (expression -> expression MINUS expression .)
+ IF reduce using rule 18 (expression -> expression MINUS expression .)
+ STRING_LITERAL reduce using rule 18 (expression -> expression MINUS expression .)
+ RIGHT_BRACE reduce using rule 18 (expression -> expression MINUS expression .)
+ RIGHT_BRACKET reduce using rule 18 (expression -> expression MINUS expression .)
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! TIMES [ reduce using rule 18 (expression -> expression MINUS expression .) ]
+ ! DIVIDE [ reduce using rule 18 (expression -> expression MINUS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 69
+
+ (19) expression -> expression TIMES expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 19 (expression -> expression TIMES expression .)
+ OR reduce using rule 19 (expression -> expression TIMES expression .)
+ PLUS reduce using rule 19 (expression -> expression TIMES expression .)
+ MINUS reduce using rule 19 (expression -> expression TIMES expression .)
+ TIMES reduce using rule 19 (expression -> expression TIMES expression .)
+ DIVIDE reduce using rule 19 (expression -> expression TIMES expression .)
+ EQUALS reduce using rule 19 (expression -> expression TIMES expression .)
+ NOT_EQUALS reduce using rule 19 (expression -> expression TIMES expression .)
+ LESS_EQUALS reduce using rule 19 (expression -> expression TIMES expression .)
+ LESS_THAN reduce using rule 19 (expression -> expression TIMES expression .)
+ GREATER_EQUALS reduce using rule 19 (expression -> expression TIMES expression .)
+ GREATER_THAN reduce using rule 19 (expression -> expression TIMES expression .)
+ IF reduce using rule 19 (expression -> expression TIMES expression .)
+ STRING_LITERAL reduce using rule 19 (expression -> expression TIMES expression .)
+ RIGHT_BRACE reduce using rule 19 (expression -> expression TIMES expression .)
+ RIGHT_BRACKET reduce using rule 19 (expression -> expression TIMES expression .)
+
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! TIMES [ shift and go to state 49 ]
+ ! DIVIDE [ shift and go to state 51 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 70
+
+ (16) expression -> expression OR expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ OR reduce using rule 16 (expression -> expression OR expression .)
+ IF reduce using rule 16 (expression -> expression OR expression .)
+ STRING_LITERAL reduce using rule 16 (expression -> expression OR expression .)
+ RIGHT_BRACE reduce using rule 16 (expression -> expression OR expression .)
+ RIGHT_BRACKET reduce using rule 16 (expression -> expression OR expression .)
+ AND shift and go to state 52
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ EQUALS shift and go to state 46
+ NOT_EQUALS shift and go to state 45
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+ ! AND [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! PLUS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! MINUS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! TIMES [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! DIVIDE [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! EQUALS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! NOT_EQUALS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! LESS_EQUALS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! LESS_THAN [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! GREATER_EQUALS [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! GREATER_THAN [ reduce using rule 16 (expression -> expression OR expression .) ]
+ ! OR [ shift and go to state 50 ]
+
+
+state 71
+
+ (20) expression -> expression DIVIDE expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 20 (expression -> expression DIVIDE expression .)
+ OR reduce using rule 20 (expression -> expression DIVIDE expression .)
+ PLUS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ MINUS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ TIMES reduce using rule 20 (expression -> expression DIVIDE expression .)
+ DIVIDE reduce using rule 20 (expression -> expression DIVIDE expression .)
+ EQUALS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ NOT_EQUALS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ LESS_EQUALS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ LESS_THAN reduce using rule 20 (expression -> expression DIVIDE expression .)
+ GREATER_EQUALS reduce using rule 20 (expression -> expression DIVIDE expression .)
+ GREATER_THAN reduce using rule 20 (expression -> expression DIVIDE expression .)
+ IF reduce using rule 20 (expression -> expression DIVIDE expression .)
+ STRING_LITERAL reduce using rule 20 (expression -> expression DIVIDE expression .)
+ RIGHT_BRACE reduce using rule 20 (expression -> expression DIVIDE expression .)
+ RIGHT_BRACKET reduce using rule 20 (expression -> expression DIVIDE expression .)
+
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! PLUS [ shift and go to state 44 ]
+ ! MINUS [ shift and go to state 48 ]
+ ! TIMES [ shift and go to state 49 ]
+ ! DIVIDE [ shift and go to state 51 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 72
+
+ (15) expression -> expression AND expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 15 (expression -> expression AND expression .)
+ OR reduce using rule 15 (expression -> expression AND expression .)
+ IF reduce using rule 15 (expression -> expression AND expression .)
+ STRING_LITERAL reduce using rule 15 (expression -> expression AND expression .)
+ RIGHT_BRACE reduce using rule 15 (expression -> expression AND expression .)
+ RIGHT_BRACKET reduce using rule 15 (expression -> expression AND expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ EQUALS shift and go to state 46
+ NOT_EQUALS shift and go to state 45
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
+ ! PLUS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! MINUS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! TIMES [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! DIVIDE [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! EQUALS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! NOT_EQUALS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! LESS_EQUALS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! LESS_THAN [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! GREATER_EQUALS [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! GREATER_THAN [ reduce using rule 15 (expression -> expression AND expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+
+
+state 73
+
+ (26) expression -> expression GREATER_THAN expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ OR reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ EQUALS reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ NOT_EQUALS reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ LESS_EQUALS reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ LESS_THAN reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ GREATER_EQUALS reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ GREATER_THAN reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ IF reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ STRING_LITERAL reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ RIGHT_BRACE reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ RIGHT_BRACKET reduce using rule 26 (expression -> expression GREATER_THAN expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! PLUS [ reduce using rule 26 (expression -> expression GREATER_THAN expression .) ]
+ ! MINUS [ reduce using rule 26 (expression -> expression GREATER_THAN expression .) ]
+ ! TIMES [ reduce using rule 26 (expression -> expression GREATER_THAN expression .) ]
+ ! DIVIDE [ reduce using rule 26 (expression -> expression GREATER_THAN expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 74
+
+ (23) expression -> expression LESS_EQUALS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ OR reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ EQUALS reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ NOT_EQUALS reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ LESS_EQUALS reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ LESS_THAN reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ GREATER_EQUALS reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ GREATER_THAN reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ IF reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ STRING_LITERAL reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ RIGHT_BRACE reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ RIGHT_BRACKET reduce using rule 23 (expression -> expression LESS_EQUALS expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! PLUS [ reduce using rule 23 (expression -> expression LESS_EQUALS expression .) ]
+ ! MINUS [ reduce using rule 23 (expression -> expression LESS_EQUALS expression .) ]
+ ! TIMES [ reduce using rule 23 (expression -> expression LESS_EQUALS expression .) ]
+ ! DIVIDE [ reduce using rule 23 (expression -> expression LESS_EQUALS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 75
+
+ (25) expression -> expression GREATER_EQUALS expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ AND reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ OR reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ EQUALS reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ NOT_EQUALS reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ LESS_EQUALS reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ LESS_THAN reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ GREATER_EQUALS reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ GREATER_THAN reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ IF reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ STRING_LITERAL reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ RIGHT_BRACE reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ RIGHT_BRACKET reduce using rule 25 (expression -> expression GREATER_EQUALS expression .)
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+
+ ! PLUS [ reduce using rule 25 (expression -> expression GREATER_EQUALS expression .) ]
+ ! MINUS [ reduce using rule 25 (expression -> expression GREATER_EQUALS expression .) ]
+ ! TIMES [ reduce using rule 25 (expression -> expression GREATER_EQUALS expression .) ]
+ ! DIVIDE [ reduce using rule 25 (expression -> expression GREATER_EQUALS expression .) ]
+ ! AND [ shift and go to state 52 ]
+ ! OR [ shift and go to state 50 ]
+ ! EQUALS [ shift and go to state 46 ]
+ ! NOT_EQUALS [ shift and go to state 45 ]
+ ! LESS_EQUALS [ shift and go to state 54 ]
+ ! LESS_THAN [ shift and go to state 47 ]
+ ! GREATER_EQUALS [ shift and go to state 55 ]
+ ! GREATER_THAN [ shift and go to state 53 ]
+
+
+state 76
+
+ (8) question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN . expression
+ (11) expression -> . LEFT_BRACKET expression RIGHT_BRACKET
+ (12) expression -> . IDENTIFIER
+ (13) expression -> . NOT expression
+ (14) expression -> . MINUS expression
+ (15) expression -> . expression AND expression
+ (16) expression -> . expression OR expression
+ (17) expression -> . expression PLUS expression
+ (18) expression -> . expression MINUS expression
+ (19) expression -> . expression TIMES expression
+ (20) expression -> . expression DIVIDE expression
+ (21) expression -> . expression EQUALS expression
+ (22) expression -> . expression NOT_EQUALS expression
+ (23) expression -> . expression LESS_EQUALS expression
+ (24) expression -> . expression LESS_THAN expression
+ (25) expression -> . expression GREATER_EQUALS expression
+ (26) expression -> . expression GREATER_THAN expression
+ (27) expression -> . FALSE
+ (28) expression -> . TRUE
+ (29) expression -> . DATE_LITERAL
+ (30) expression -> . INTEGER_LITERAL
+ (31) expression -> . DECIMAL_LITERAL
+ (32) expression -> . currency DECIMAL_LITERAL
+ (33) expression -> . currency INTEGER_LITERAL
+ (34) expression -> . STRING_LITERAL
+ (35) currency -> . DOLLAR
+ (36) currency -> . RUBLE
+
+ LEFT_BRACKET shift and go to state 30
+ IDENTIFIER shift and go to state 34
+ NOT shift and go to state 27
+ MINUS shift and go to state 25
+ FALSE shift and go to state 35
+ TRUE shift and go to state 32
+ DATE_LITERAL shift and go to state 24
+ INTEGER_LITERAL shift and go to state 26
+ DECIMAL_LITERAL shift and go to state 31
+ STRING_LITERAL shift and go to state 28
+ DOLLAR shift and go to state 29
+ RUBLE shift and go to state 23
+
+ expression shift and go to state 77
+ currency shift and go to state 22
+
+state 77
+
+ (8) question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression .
+ (15) expression -> expression . AND expression
+ (16) expression -> expression . OR expression
+ (17) expression -> expression . PLUS expression
+ (18) expression -> expression . MINUS expression
+ (19) expression -> expression . TIMES expression
+ (20) expression -> expression . DIVIDE expression
+ (21) expression -> expression . EQUALS expression
+ (22) expression -> expression . NOT_EQUALS expression
+ (23) expression -> expression . LESS_EQUALS expression
+ (24) expression -> expression . LESS_THAN expression
+ (25) expression -> expression . GREATER_EQUALS expression
+ (26) expression -> expression . GREATER_THAN expression
+
+ IF reduce using rule 8 (question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression .)
+ STRING_LITERAL reduce using rule 8 (question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression .)
+ RIGHT_BRACE reduce using rule 8 (question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression .)
+ AND shift and go to state 52
+ OR shift and go to state 50
+ PLUS shift and go to state 44
+ MINUS shift and go to state 48
+ TIMES shift and go to state 49
+ DIVIDE shift and go to state 51
+ EQUALS shift and go to state 46
+ NOT_EQUALS shift and go to state 45
+ LESS_EQUALS shift and go to state 54
+ LESS_THAN shift and go to state 47
+ GREATER_EQUALS shift and go to state 55
+ GREATER_THAN shift and go to state 53
+
diff --git a/ql/parser/parser.py b/ql/parser/parser.py
new file mode 100644
index 0000000..d962a0f
--- /dev/null
+++ b/ql/parser/parser.py
@@ -0,0 +1,319 @@
+from ply.yacc import yacc
+
+from ql.ast.nodes.expressions.binary_operators.addition_operator import AdditionOperatorNode
+from ql.ast.nodes.expressions.binary_operators.and_operator import AndOperatorNode
+from ql.ast.nodes.expressions.binary_operators.division_operator import DivisionOperatorNode
+from ql.ast.nodes.expressions.binary_operators.equals_operator import EqualsOperatorNode
+from ql.ast.nodes.expressions.binary_operators.greater_equals_operator import GreaterEqualsOperatorNode
+from ql.ast.nodes.expressions.binary_operators.greater_than_operator import GreaterThanOperatorNode
+from ql.ast.nodes.expressions.binary_operators.less_equals_operator import LessEqualsOperatorNode
+from ql.ast.nodes.expressions.binary_operators.less_than_operator import LessThanOperatorNode
+from ql.ast.nodes.expressions.binary_operators.multiplication_operator import MultiplicationOperatorNode
+from ql.ast.nodes.expressions.binary_operators.not_equals_operator import NotEqualsOperatorNode
+from ql.ast.nodes.expressions.binary_operators.or_operator import OrOperatorNode
+from ql.ast.nodes.expressions.binary_operators.subtraction_operator import SubtractionOperatorNode
+from ql.ast.nodes.expressions.literals.boolean_literal import BooleanNode
+from ql.ast.nodes.expressions.literals.date_literal import DateNode
+from ql.ast.nodes.expressions.literals.decimal_literal import DecimalNode
+from ql.ast.nodes.expressions.literals.integer_literal import IntegerNode
+from ql.ast.nodes.expressions.literals.money_literal import MoneyNode
+from ql.ast.nodes.expressions.literals.string_literal import StringNode
+from ql.ast.nodes.expressions.unary_operators.negation_operator import NegationOperatorNode
+from ql.ast.nodes.expressions.unary_operators.negative_operator import NegativeOperatorNode
+from ql.ast.nodes.expressions.variable import VariableNode
+from ql.ast.nodes.statements.form_statement import FormNode
+from ql.ast.nodes.statements.if_statement import IfNode
+from ql.ast.nodes.statements.question_statement import QuestionNode
+from ql.parser.lexer import QLLexer
+from ql.parser.metadata import Metadata
+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.types.undefined import QLUndefined
+
+
+class QLParser:
+ def __init__(self):
+ self.__errors = []
+ self.__tokens = QLLexer.tokens
+ self.__parser = None
+ self.__precedence = (
+ ('left', 'OR'),
+ ('left', 'AND'),
+ ('nonassoc', 'EQUALS', 'NOT_EQUALS'),
+ ('nonassoc', 'LESS_EQUALS', 'LESS_THAN', 'GREATER_EQUALS', 'GREATER_THAN'),
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'NOT'),
+ )
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ @property
+ def tokens(self):
+ return self.__tokens
+
+ @property
+ def parser(self):
+ return self.__parser
+
+ @property
+ def precedence(self):
+ return self.__precedence
+
+ def build(self):
+ self.__parser = yacc(module=self)
+
+ def parse(self, data, lexer):
+ self.__errors = []
+ return self.parser.parse(data, lexer)
+
+ # Grammar
+ @staticmethod
+ def p_form(production):
+ """form : FORM IDENTIFIER block"""
+ production[0] = FormNode(Metadata(production.lineno(1)), production[3], production[2])
+
+ @staticmethod
+ def p_block(production):
+ """block : LEFT_BRACE statements RIGHT_BRACE"""
+ production[0] = production[2]
+
+ # Statements
+ @staticmethod
+ def p_statements(production):
+ """statements : statement statements
+ | statement"""
+ if len(production) == 3:
+ production[0] = [production[1]] + production[2]
+ elif len(production) == 2:
+ production[0] = [production[1]]
+
+ @staticmethod
+ def p_statement(production):
+ """statement : if
+ | question"""
+ production[0] = production[1]
+
+ # Questions
+ @staticmethod
+ def p_question(production):
+ """question : STRING_LITERAL IDENTIFIER COLON type"""
+ production[0] = QuestionNode(Metadata(production.lineno(1)), production[1], production[2],
+ production[4], production[4].get_literal_node(production[4]()), False)
+
+ @staticmethod
+ def p_question_computed(production):
+ """question : STRING_LITERAL IDENTIFIER COLON type ASSIGN expression"""
+ production[0] = QuestionNode(Metadata(production.lineno(1)), production[1], production[2],
+ production[4], production[6], True)
+
+ # Control flow
+ @staticmethod
+ def p_if(production):
+ """if : IF condition block"""
+ production[0] = IfNode(Metadata(production.lineno(1)), production[3], production[2])
+
+ @staticmethod
+ def p_condition(production):
+ """condition : LEFT_BRACKET expression RIGHT_BRACKET"""
+ production[0] = production[2]
+
+ # Expressions
+ @staticmethod
+ def p_parenthesis(production):
+ """expression : LEFT_BRACKET expression RIGHT_BRACKET"""
+ production[0] = production[2]
+
+ @staticmethod
+ def p_variable(production):
+ """expression : IDENTIFIER"""
+ production[0] = VariableNode(Metadata(production.lineno(1)), QLUndefined, production[1],
+ QLUndefined())
+
+ # Unary operators
+ @staticmethod
+ def p_not(production):
+ """expression : NOT expression"""
+ production[0] = NegationOperatorNode(Metadata(production.lineno(1)), QLBoolean,
+ production[2], QLUndefined())
+
+ @staticmethod
+ def p_negative(production):
+ """expression : MINUS expression"""
+ production[0] = NegativeOperatorNode(Metadata(production.lineno(1)), QLUndefined,
+ production[2], QLUndefined())
+
+ # Binary operators
+ @staticmethod
+ def p_and(production):
+ """expression : expression AND expression"""
+ production[0] = AndOperatorNode(Metadata(production.lineno(2)), QLBoolean, production[1],
+ production[3], QLUndefined())
+
+ @staticmethod
+ def p_or(production):
+ """expression : expression OR expression"""
+ production[0] = OrOperatorNode(Metadata(production.lineno(2)), QLBoolean, production[1],
+ production[3], QLUndefined())
+
+ @staticmethod
+ def p_plus(production):
+ """expression : expression PLUS expression"""
+ production[0] = AdditionOperatorNode(Metadata(production.lineno(2)), QLUndefined,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_minus(production):
+ """expression : expression MINUS expression"""
+ production[0] = SubtractionOperatorNode(Metadata(production.lineno(2)), QLUndefined,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_times(production):
+ """expression : expression TIMES expression"""
+ production[0] = MultiplicationOperatorNode(Metadata(production.lineno(2)), QLUndefined,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_divide(production):
+ """expression : expression DIVIDE expression"""
+ production[0] = DivisionOperatorNode(Metadata(production.lineno(2)), QLUndefined,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_equals(production):
+ """expression : expression EQUALS expression"""
+ production[0] = EqualsOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_not_equals(production):
+ """expression : expression NOT_EQUALS expression"""
+ production[0] = NotEqualsOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_less_equals(production):
+ """expression : expression LESS_EQUALS expression"""
+ production[0] = LessEqualsOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_less_than(production):
+ """expression : expression LESS_THAN expression"""
+ production[0] = LessThanOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_greater_equals(production):
+ """expression : expression GREATER_EQUALS expression"""
+ production[0] = GreaterEqualsOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ @staticmethod
+ def p_greater_than(production):
+ """expression : expression GREATER_THAN expression"""
+ production[0] = GreaterThanOperatorNode(Metadata(production.lineno(2)), QLBoolean,
+ production[1], production[3], QLUndefined())
+
+ # Literals
+ @staticmethod
+ def p_boolean_literal(production):
+ """expression : FALSE
+ | TRUE"""
+ production[0] = BooleanNode(Metadata(production.lineno(1)), QLBoolean, QLBoolean(production[1]))
+
+ @staticmethod
+ def p_date_literal(production):
+ """expression : DATE_LITERAL"""
+ day, month, year = production[1]
+ production[0] = DateNode(Metadata(production.lineno(1)), QLDate, QLDate(day, month, year))
+
+ @staticmethod
+ def p_integer_literal(production):
+ """expression : INTEGER_LITERAL"""
+ production[0] = IntegerNode(Metadata(production.lineno(1)), QLInteger, QLInteger(production[1]))
+
+ @staticmethod
+ def p_decimal_literal(production):
+ """expression : DECIMAL_LITERAL"""
+ production[0] = DecimalNode(Metadata(production.lineno(1)), QLDecimal, QLDecimal(production[1]))
+
+ @staticmethod
+ def p_money_literal(production):
+ """expression : currency DECIMAL_LITERAL
+ | currency INTEGER_LITERAL"""
+ production[0] = MoneyNode(Metadata(production.lineno(1)), QLMoney,
+ QLMoney(production[2], production[1]))
+
+ @staticmethod
+ def p_string_literal(production):
+ """expression : STRING_LITERAL"""
+ production[0] = StringNode(Metadata(production.lineno(1)), QLString, QLString([1]))
+
+ # Currencies
+ @staticmethod
+ def p_currency(production):
+ """currency : DOLLAR
+ | RUBLE"""
+ production[0] = production[1]
+
+ # Types
+ @staticmethod
+ def p_boolean(production):
+ """type : BOOLEAN"""
+ production[0] = QLBoolean
+
+ @staticmethod
+ def p_decimal(production):
+ """type : DECIMAL"""
+ production[0] = QLDecimal
+
+ @staticmethod
+ def p_string(production):
+ """type : STRING"""
+ production[0] = QLString
+
+ @staticmethod
+ def p_date(production):
+ """type : DATE"""
+ production[0] = QLDate
+
+ @staticmethod
+ def p_money(production):
+ """type : MONEY"""
+ production[0] = QLMoney
+
+ @staticmethod
+ def p_integer(production):
+ """type : INTEGER"""
+ production[0] = QLInteger
+
+ # Error
+ def p_error(self, production):
+ if production is None:
+ self.errors.append('Syntax error.')
+ else:
+ self.errors.append('Syntax error at line {}, token={}.'.format(production.lineno, production.type))
+
+ def p_form_label(self, production):
+ """form : FORM LEFT_BRACE"""
+ self.errors.append('Missing form identifier at line {}.'.format(production.lineno(1)))
+
+ def p_empty_form(self, production):
+ """form : FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE"""
+ self.errors.append('Empty form at line {}.'.format(production.lineno(1)))
+
+ def p_empty_if(self, production):
+ """statement : IF condition LEFT_BRACE RIGHT_BRACE"""
+ self.errors.append('Empty if block at line {}.'.format(production.lineno(1)))
+
+ def p_empty_condition(self, production):
+ """condition : LEFT_BRACKET RIGHT_BRACKET"""
+ self.errors.append('Empty conditional at line {}.'.format(production.lineno(1)))
diff --git a/ql/parser/parsetab.py b/ql/parser/parsetab.py
new file mode 100644
index 0000000..b978ef8
--- /dev/null
+++ b/ql/parser/parsetab.py
@@ -0,0 +1,76 @@
+
+# parsetab.py
+# This file is automatically generated. Do not edit.
+# pylint: disable=W,C,R
+_tabversion = '3.10'
+
+_lr_method = 'LALR'
+
+_lr_signature = 'leftORleftANDnonassocEQUALSNOT_EQUALSnonassocLESS_EQUALSLESS_THANGREATER_EQUALSGREATER_THANleftPLUSMINUSleftTIMESDIVIDErightNOTAND ASSIGN BOOLEAN COLON DATE DATE_LITERAL DECIMAL DECIMAL_LITERAL DIVIDE DOLLAR EQUALS FALSE FORM GREATER_EQUALS GREATER_THAN IDENTIFIER IF INTEGER INTEGER_LITERAL LEFT_BRACE LEFT_BRACKET LESS_EQUALS LESS_THAN MINUS MONEY NOT NOT_EQUALS OR PLUS RIGHT_BRACE RIGHT_BRACKET RUBLE STRING STRING_LITERAL TIMES TRUEform : FORM IDENTIFIER blockblock : LEFT_BRACE statements RIGHT_BRACEstatements : statement statements\n | statementstatement : if\n | questionquestion : STRING_LITERAL IDENTIFIER COLON typequestion : STRING_LITERAL IDENTIFIER COLON type ASSIGN expressionif : IF condition blockcondition : LEFT_BRACKET expression RIGHT_BRACKETexpression : LEFT_BRACKET expression RIGHT_BRACKETexpression : IDENTIFIERexpression : NOT expressionexpression : MINUS expressionexpression : expression AND expressionexpression : expression OR expressionexpression : expression PLUS expressionexpression : expression MINUS expressionexpression : expression TIMES expressionexpression : expression DIVIDE expressionexpression : expression EQUALS expressionexpression : expression NOT_EQUALS expressionexpression : expression LESS_EQUALS expressionexpression : expression LESS_THAN expressionexpression : expression GREATER_EQUALS expressionexpression : expression GREATER_THAN expressionexpression : FALSE\n | TRUEexpression : DATE_LITERALexpression : INTEGER_LITERALexpression : DECIMAL_LITERALexpression : currency DECIMAL_LITERAL\n | currency INTEGER_LITERALexpression : STRING_LITERALcurrency : DOLLAR\n | RUBLEtype : BOOLEANtype : DECIMALtype : STRINGtype : DATEtype : MONEYtype : INTEGERform : FORM LEFT_BRACEform : FORM IDENTIFIER LEFT_BRACE RIGHT_BRACEstatement : IF condition LEFT_BRACE RIGHT_BRACEcondition : LEFT_BRACKET RIGHT_BRACKET'
+
+_lr_action_items = {'RIGHT_BRACKET':([17,24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,],[21,-29,-30,-34,-31,-28,43,-12,-27,-32,-33,-14,-13,63,-11,-17,-22,-21,-24,-18,-19,-16,-20,-15,-26,-23,-25,]),'TRUE':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,]),'LEFT_BRACE':([1,3,16,21,43,],[4,5,19,-46,-10,]),'RUBLE':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,]),'DATE_LITERAL':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,]),'MINUS':([17,24,25,26,27,28,30,31,32,33,34,35,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,],[25,-29,25,-30,25,-34,25,-31,-28,48,-12,-27,-32,-33,-14,-13,48,25,25,25,25,25,25,25,25,25,25,25,25,-11,-17,48,48,48,-18,-19,48,-20,48,48,48,48,25,48,]),'INTEGER_LITERAL':([17,22,23,25,27,29,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[26,39,-36,26,26,-35,26,26,26,26,26,26,26,26,26,26,26,26,26,26,]),'TIMES':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,49,-12,-27,-32,-33,49,-13,49,-11,49,49,49,49,49,-19,49,-20,49,49,49,49,49,]),'NOT':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,]),'DOLLAR':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'MONEY':([36,],[60,]),'INTEGER':([36,],[61,]),'AND':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,52,-12,-27,-32,-33,-14,-13,52,-11,-17,-22,-21,-24,-18,-19,52,-20,-15,-26,-23,-25,52,]),'NOT_EQUALS':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,45,-12,-27,-32,-33,-14,-13,45,-11,-17,None,None,-24,-18,-19,45,-20,45,-26,-23,-25,45,]),'ASSIGN':([56,57,58,59,60,61,62,],[-40,-38,-39,76,-41,-42,-37,]),'BOOLEAN':([36,],[62,]),'FORM':([0,],[1,]),'IF':([5,7,8,10,14,19,20,24,26,28,31,32,34,35,37,38,39,40,41,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[11,-5,-6,11,-2,11,-9,-29,-30,-34,-31,-28,-12,-27,-45,-32,-33,-14,-13,-40,-38,-39,-7,-41,-42,-37,-11,-17,-22,-21,-24,-18,-19,-16,-20,-15,-26,-23,-25,-8,]),'LEFT_BRACKET':([11,17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[17,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,]),'PLUS':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,44,-12,-27,-32,-33,-14,-13,44,-11,-17,44,44,44,-18,-19,44,-20,44,44,44,44,44,]),'$end':([2,4,6,13,14,],[0,-43,-1,-44,-2,]),'EQUALS':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,46,-12,-27,-32,-33,-14,-13,46,-11,-17,None,None,-24,-18,-19,46,-20,46,-26,-23,-25,46,]),'IDENTIFIER':([1,12,17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[3,18,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,]),'LESS_THAN':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,47,-12,-27,-32,-33,-14,-13,47,-11,-17,47,47,None,-18,-19,47,-20,47,None,None,None,47,]),'STRING':([36,],[58,]),'COLON':([18,],[36,]),'DATE':([36,],[56,]),'STRING_LITERAL':([5,7,8,10,14,17,19,20,24,25,26,27,28,30,31,32,34,35,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,],[12,-5,-6,12,-2,28,12,-9,-29,28,-30,28,-34,28,-31,-28,-12,-27,-45,-32,-33,-14,-13,28,28,28,28,28,28,28,28,28,28,28,28,-40,-38,-39,-7,-41,-42,-37,-11,-17,-22,-21,-24,-18,-19,-16,-20,-15,-26,-23,-25,28,-8,]),'DECIMAL_LITERAL':([17,22,23,25,27,29,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[31,38,-36,31,31,-35,31,31,31,31,31,31,31,31,31,31,31,31,31,31,]),'OR':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,50,-12,-27,-32,-33,-14,-13,50,-11,-17,-22,-21,-24,-18,-19,-16,-20,-15,-26,-23,-25,50,]),'FALSE':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,]),'DECIMAL':([36,],[57,]),'DIVIDE':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,51,-12,-27,-32,-33,51,-13,51,-11,51,51,51,51,51,-19,51,-20,51,51,51,51,51,]),'LESS_EQUALS':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,54,-12,-27,-32,-33,-14,-13,54,-11,-17,54,54,None,-18,-19,54,-20,54,None,None,None,54,]),'RIGHT_BRACE':([5,7,8,9,10,14,15,19,20,24,26,28,31,32,34,35,37,38,39,40,41,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[13,-5,-6,14,-4,-2,-3,37,-9,-29,-30,-34,-31,-28,-12,-27,-45,-32,-33,-14,-13,-40,-38,-39,-7,-41,-42,-37,-11,-17,-22,-21,-24,-18,-19,-16,-20,-15,-26,-23,-25,-8,]),'GREATER_EQUALS':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,55,-12,-27,-32,-33,-14,-13,55,-11,-17,55,55,None,-18,-19,55,-20,55,None,None,None,55,]),'GREATER_THAN':([24,26,28,31,32,33,34,35,38,39,40,41,42,63,64,65,66,67,68,69,70,71,72,73,74,75,77,],[-29,-30,-34,-31,-28,53,-12,-27,-32,-33,-14,-13,53,-11,-17,53,53,None,-18,-19,53,-20,53,None,None,None,53,]),}
+
+_lr_action = {}
+for _k, _v in _lr_action_items.items():
+ for _x,_y in zip(_v[0],_v[1]):
+ if not _x in _lr_action: _lr_action[_x] = {}
+ _lr_action[_x][_k] = _y
+del _lr_action_items
+
+_lr_goto_items = {'if':([5,10,19,],[7,7,7,]),'condition':([11,],[16,]),'question':([5,10,19,],[8,8,8,]),'expression':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[33,40,41,42,64,65,66,67,68,69,70,71,72,73,74,75,77,]),'currency':([17,25,27,30,44,45,46,47,48,49,50,51,52,53,54,55,76,],[22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,]),'type':([36,],[59,]),'statements':([5,10,19,],[9,15,9,]),'statement':([5,10,19,],[10,10,10,]),'form':([0,],[2,]),'block':([3,16,],[6,20,]),}
+
+_lr_goto = {}
+for _k, _v in _lr_goto_items.items():
+ for _x, _y in zip(_v[0], _v[1]):
+ if not _x in _lr_goto: _lr_goto[_x] = {}
+ _lr_goto[_x][_k] = _y
+del _lr_goto_items
+_lr_productions = [
+ ("S' -> form","S'",1,None,None,None),
+ ('form -> FORM IDENTIFIER block','form',3,'p_form','parser.py',78),
+ ('block -> LEFT_BRACE statements RIGHT_BRACE','block',3,'p_block','parser.py',83),
+ ('statements -> statement statements','statements',2,'p_statements','parser.py',89),
+ ('statements -> statement','statements',1,'p_statements','parser.py',90),
+ ('statement -> if','statement',1,'p_statement','parser.py',98),
+ ('statement -> question','statement',1,'p_statement','parser.py',99),
+ ('question -> STRING_LITERAL IDENTIFIER COLON type','question',4,'p_question','parser.py',105),
+ ('question -> STRING_LITERAL IDENTIFIER COLON type ASSIGN expression','question',6,'p_question_computed','parser.py',111),
+ ('if -> IF condition block','if',3,'p_if','parser.py',118),
+ ('condition -> LEFT_BRACKET expression RIGHT_BRACKET','condition',3,'p_condition','parser.py',123),
+ ('expression -> LEFT_BRACKET expression RIGHT_BRACKET','expression',3,'p_parenthesis','parser.py',129),
+ ('expression -> IDENTIFIER','expression',1,'p_variable','parser.py',134),
+ ('expression -> NOT expression','expression',2,'p_not','parser.py',141),
+ ('expression -> MINUS expression','expression',2,'p_negative','parser.py',147),
+ ('expression -> expression AND expression','expression',3,'p_and','parser.py',154),
+ ('expression -> expression OR expression','expression',3,'p_or','parser.py',160),
+ ('expression -> expression PLUS expression','expression',3,'p_plus','parser.py',166),
+ ('expression -> expression MINUS expression','expression',3,'p_minus','parser.py',172),
+ ('expression -> expression TIMES expression','expression',3,'p_times','parser.py',178),
+ ('expression -> expression DIVIDE expression','expression',3,'p_divide','parser.py',184),
+ ('expression -> expression EQUALS expression','expression',3,'p_equals','parser.py',190),
+ ('expression -> expression NOT_EQUALS expression','expression',3,'p_not_equals','parser.py',196),
+ ('expression -> expression LESS_EQUALS expression','expression',3,'p_less_equals','parser.py',202),
+ ('expression -> expression LESS_THAN expression','expression',3,'p_less_than','parser.py',208),
+ ('expression -> expression GREATER_EQUALS expression','expression',3,'p_greater_equals','parser.py',214),
+ ('expression -> expression GREATER_THAN expression','expression',3,'p_greater_than','parser.py',220),
+ ('expression -> FALSE','expression',1,'p_boolean_literal','parser.py',227),
+ ('expression -> TRUE','expression',1,'p_boolean_literal','parser.py',228),
+ ('expression -> DATE_LITERAL','expression',1,'p_date_literal','parser.py',233),
+ ('expression -> INTEGER_LITERAL','expression',1,'p_integer_literal','parser.py',238),
+ ('expression -> DECIMAL_LITERAL','expression',1,'p_decimal_literal','parser.py',243),
+ ('expression -> currency DECIMAL_LITERAL','expression',2,'p_money_literal','parser.py',248),
+ ('expression -> currency INTEGER_LITERAL','expression',2,'p_money_literal','parser.py',249),
+ ('expression -> STRING_LITERAL','expression',1,'p_string_literal','parser.py',255),
+ ('currency -> DOLLAR','currency',1,'p_currency','parser.py',261),
+ ('currency -> RUBLE','currency',1,'p_currency','parser.py',262),
+ ('type -> BOOLEAN','type',1,'p_boolean','parser.py',268),
+ ('type -> DECIMAL','type',1,'p_decimal','parser.py',273),
+ ('type -> STRING','type',1,'p_string','parser.py',278),
+ ('type -> DATE','type',1,'p_date','parser.py',283),
+ ('type -> MONEY','type',1,'p_money','parser.py',288),
+ ('type -> INTEGER','type',1,'p_integer','parser.py',293),
+ ('form -> FORM LEFT_BRACE','form',2,'p_form_label','parser.py',305),
+ ('form -> FORM IDENTIFIER LEFT_BRACE RIGHT_BRACE','form',4,'p_empty_form','parser.py',309),
+ ('statement -> IF condition LEFT_BRACE RIGHT_BRACE','statement',4,'p_empty_if','parser.py',313),
+ ('condition -> LEFT_BRACKET RIGHT_BRACKET','condition',2,'p_empty_condition','parser.py',317),
+]
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())
diff --git a/ql/types/__pycache__/boolean.cpython-35.pyc b/ql/types/__pycache__/boolean.cpython-35.pyc
new file mode 100644
index 0000000..0acd5ee
--- /dev/null
+++ b/ql/types/__pycache__/boolean.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/date.cpython-35.pyc b/ql/types/__pycache__/date.cpython-35.pyc
new file mode 100644
index 0000000..389ffc4
--- /dev/null
+++ b/ql/types/__pycache__/date.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/decimal.cpython-35.pyc b/ql/types/__pycache__/decimal.cpython-35.pyc
new file mode 100644
index 0000000..03e70c2
--- /dev/null
+++ b/ql/types/__pycache__/decimal.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/integer.cpython-35.pyc b/ql/types/__pycache__/integer.cpython-35.pyc
new file mode 100644
index 0000000..eacf953
--- /dev/null
+++ b/ql/types/__pycache__/integer.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/money.cpython-35.pyc b/ql/types/__pycache__/money.cpython-35.pyc
new file mode 100644
index 0000000..4213628
--- /dev/null
+++ b/ql/types/__pycache__/money.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/string.cpython-35.pyc b/ql/types/__pycache__/string.cpython-35.pyc
new file mode 100644
index 0000000..18b2f54
--- /dev/null
+++ b/ql/types/__pycache__/string.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/type.cpython-35.pyc b/ql/types/__pycache__/type.cpython-35.pyc
new file mode 100644
index 0000000..f81c2f7
--- /dev/null
+++ b/ql/types/__pycache__/type.cpython-35.pyc
Binary files differ
diff --git a/ql/types/__pycache__/undefined.cpython-35.pyc b/ql/types/__pycache__/undefined.cpython-35.pyc
new file mode 100644
index 0000000..ddc6cc1
--- /dev/null
+++ b/ql/types/__pycache__/undefined.cpython-35.pyc
Binary files differ
diff --git a/ql/types/boolean.py b/ql/types/boolean.py
new file mode 100644
index 0000000..f9dc76c
--- /dev/null
+++ b/ql/types/boolean.py
@@ -0,0 +1,42 @@
+from gui.widgets.checkbox import CheckBox
+from ql.ast.nodes.expressions.literals.boolean_literal import BooleanNode
+from ql.types.type import QLType
+
+
+class QLBoolean(QLType):
+ def __init__(self, value=False):
+ super(QLBoolean, self).__init__()
+ self.__value = bool(value)
+
+ @property
+ def value(self):
+ return self.__value
+
+ def __bool__(self):
+ return bool(self.value)
+
+ def __str__(self):
+ return str(self.value)
+
+ def __repr__(self):
+ return str(self.value)
+
+ def __eq__(self, other):
+ if isinstance(other, QLBoolean):
+ return QLBoolean(self.value == other.value)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def get_json_value(self):
+ return self.value
+
+ @staticmethod
+ def get_literal_node(value):
+ return BooleanNode(None, QLBoolean, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return CheckBox()
diff --git a/ql/types/date.py b/ql/types/date.py
new file mode 100644
index 0000000..fca5366
--- /dev/null
+++ b/ql/types/date.py
@@ -0,0 +1,67 @@
+from datetime import date
+
+from gui.widgets.calendar import CalendarWidget
+from ql.ast.nodes.expressions.literals.date_literal import DateNode
+from ql.types.boolean import QLBoolean
+from ql.types.type import QLType
+
+
+class QLDate(QLType):
+ def __init__(self, day=1, month=1, year=1):
+ super(QLDate, self).__init__()
+ self.__day = int(day)
+ self.__month = int(month)
+ self.__year = int(year)
+ date(self.year, self.month, self.day)
+
+ @property
+ def day(self):
+ return self.__day
+
+ @property
+ def month(self):
+ return self.__month
+
+ @property
+ def year(self):
+ return self.__year
+
+ def __repr__(self):
+ return '{}-{}-{}'.format(self.day, self.month, self.year)
+
+ def __str__(self):
+ return '{}-{}-{}'.format(self.day, self.month, self.year)
+
+ def __eq__(self, other):
+ if isinstance(other, QLDate):
+ return QLBoolean(self.day == other.day and self.month == other.month and self.year == other.year)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def __lt__(self, other):
+ return QLBoolean(self.year < other.year or (self.month < other.month and self.year == other.year) or
+ (self.day < other.day and self.month == other.month and self.year == other.year))
+
+ def __gt__(self, other):
+ return QLBoolean(self.year > other.year or (self.month > other.month and self.year == other.year) or
+ (self.day > other.day and self.month == other.month and self.year == other.year))
+
+ def __le__(self, other):
+ return QLBoolean(self < other or self == other)
+
+ def __ge__(self, other):
+ return QLBoolean(self > other or self == other)
+
+ def get_json_value(self):
+ return {'day': self.day, 'month': self.month, 'year': self.year}
+
+ @staticmethod
+ def get_literal_node(value):
+ return DateNode(None, QLDate, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return CalendarWidget()
diff --git a/ql/types/decimal.py b/ql/types/decimal.py
new file mode 100644
index 0000000..af0952d
--- /dev/null
+++ b/ql/types/decimal.py
@@ -0,0 +1,74 @@
+from gui.widgets.double_spinbox import DoubleSpinBox
+from ql.ast.nodes.expressions.literals.decimal_literal import DecimalNode
+from ql.types.boolean import QLBoolean
+from ql.types.money import QLMoney
+from ql.types.type import QLType
+
+
+class QLDecimal(QLType):
+ def __init__(self, value=0.0):
+ super(QLDecimal, self).__init__()
+ self.__value = float(value)
+
+ @property
+ def value(self):
+ return self.__value
+
+ def __repr__(self):
+ return str(self.value)
+
+ def __str__(self):
+ return str(self.value)
+
+ def __neg__(self):
+ return QLDecimal(- self.value)
+
+ def __eq__(self, other):
+ if isinstance(other, QLDecimal):
+ return QLBoolean(self.value == other.value)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def __lt__(self, other):
+ return QLBoolean(self.value < other.value)
+
+ def __gt__(self, other):
+ return QLBoolean(self.value > other.value)
+
+ def __le__(self, other):
+ return QLBoolean(self.value <= other.value)
+
+ def __ge__(self, other):
+ return QLBoolean(self.value >= other.value)
+
+ def __add__(self, other):
+ return QLDecimal(self.value + other.value)
+
+ def __sub__(self, other):
+ return QLDecimal(self.value - other.value)
+
+ def __mul__(self, other):
+ if isinstance(other, QLMoney):
+ return QLMoney(self.value * other.value, other.currency)
+
+ return QLDecimal(self.value * other.value)
+
+ def __truediv__(self, other):
+ if isinstance(other, QLMoney):
+ return QLMoney(other.value / self.value, other.currency)
+
+ return QLDecimal(self.value / other.value)
+
+ def get_json_value(self):
+ return self.value
+
+ @staticmethod
+ def get_literal_node(value):
+ return DecimalNode(None, QLDecimal, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return DoubleSpinBox()
diff --git a/ql/types/integer.py b/ql/types/integer.py
new file mode 100644
index 0000000..ddc8666
--- /dev/null
+++ b/ql/types/integer.py
@@ -0,0 +1,75 @@
+from gui.widgets.spinbox import SpinBox
+from ql.ast.nodes.expressions.literals.integer_literal import IntegerNode
+from ql.types.boolean import QLBoolean
+from ql.types.decimal import QLDecimal
+from ql.types.money import QLMoney
+from ql.types.type import QLType
+
+
+class QLInteger(QLType):
+ def __init__(self, value=0):
+ super(QLInteger, self).__init__()
+ self.__value = int(value)
+
+ @property
+ def value(self):
+ return self.__value
+
+ def __repr__(self):
+ return str(self.value)
+
+ def __str__(self):
+ return str(self.value)
+
+ def __neg__(self):
+ return QLInteger(- self.value)
+
+ def __eq__(self, other):
+ if isinstance(other, QLInteger):
+ return QLBoolean(self.value == other.value)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def __lt__(self, other):
+ return QLBoolean(self.value < other.value)
+
+ def __gt__(self, other):
+ return QLBoolean(self.value > other.value)
+
+ def __le__(self, other):
+ return QLBoolean(self.value <= other.value)
+
+ def __ge__(self, other):
+ return QLBoolean(self.value >= other.value)
+
+ def __add__(self, other):
+ return type(other)(self.value + other.value)
+
+ def __sub__(self, other):
+ return type(other)(self.value - other.value)
+
+ def __mul__(self, other):
+ if isinstance(other, QLMoney):
+ return QLMoney(self.value * other.value, other.currency)
+
+ return type(other)(self.value * other.value)
+
+ def __truediv__(self, other):
+ if isinstance(other, QLMoney):
+ return QLMoney(other.value / self.value, other.currency)
+
+ return QLDecimal(self.value / other.value)
+
+ def get_json_value(self):
+ return self.value
+
+ @staticmethod
+ def get_literal_node(value):
+ return IntegerNode(None, QLInteger, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return SpinBox()
diff --git a/ql/types/money.py b/ql/types/money.py
new file mode 100644
index 0000000..edac58f
--- /dev/null
+++ b/ql/types/money.py
@@ -0,0 +1,76 @@
+from gui.widgets.money_spinbox import MoneySpinbox
+from ql.ast.nodes.expressions.literals.money_literal import MoneyNode
+from ql.types.boolean import QLBoolean
+from ql.types.type import QLType
+
+
+class QLMoney(QLType):
+ def __init__(self, value=0.0, currency='$'):
+ super(QLMoney, self).__init__()
+ self.__value = float(value)
+ self.__currency = currency
+
+ @property
+ def value(self):
+ return self.__value
+
+ @property
+ def currency(self):
+ return self.__currency
+
+ def __repr__(self):
+ return '{}{:.2f}'.format(self.currency, self.value)
+
+ def __str__(self):
+ return '{}{:.2f}'.format(self.currency, self.value)
+
+ def __neg__(self):
+ return QLMoney(- self.value, self.currency)
+
+ def __eq__(self, other):
+ if isinstance(other, QLMoney):
+ return QLBoolean(self.value == other.value and self.currency == other.currency)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def __lt__(self, other):
+ return QLBoolean(self.value < other.value and self.currency == other.currency)
+
+ def __gt__(self, other):
+ return QLBoolean(self.value > other.value and self.currency == other.currency)
+
+ def __le__(self, other):
+ return QLBoolean(self.value <= other.value and self.currency == other.currency)
+
+ def __ge__(self, other):
+ return QLBoolean(self.value >= other.value and self.currency == other.currency)
+
+ def __add__(self, other):
+ if self.currency == other.currency:
+ return QLMoney(self.value + other.value, self.currency)
+ return NotImplemented
+
+ def __sub__(self, other):
+ if self.currency == other.currency:
+ return QLMoney(self.value - other.value, self.currency)
+ return NotImplemented
+
+ def __mul__(self, other):
+ return other * self
+
+ def __truediv__(self, other):
+ return other / self
+
+ def get_json_value(self):
+ return {'value': round(self.value, 2), 'currency': self.currency}
+
+ @staticmethod
+ def get_literal_node(value):
+ return MoneyNode(None, QLMoney, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return MoneySpinbox()
diff --git a/ql/types/string.py b/ql/types/string.py
new file mode 100644
index 0000000..ece46a7
--- /dev/null
+++ b/ql/types/string.py
@@ -0,0 +1,55 @@
+from gui.widgets.line_edit import LineEdit
+from ql.ast.nodes.expressions.literals.string_literal import StringNode
+from ql.types.boolean import QLBoolean
+from ql.types.type import QLType
+
+
+class QLString(QLType):
+ def __init__(self, value=''):
+ super(QLString, self).__init__()
+ self.__value = str(value)
+
+ @property
+ def value(self):
+ return self.__value
+
+ def __repr__(self):
+ return str(self.value)
+
+ def __str__(self):
+ return str(self.value)
+
+ def __eq__(self, other):
+ if isinstance(other, QLString):
+ return QLBoolean(self.value == other.value)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def __lt__(self, other):
+ return QLBoolean(len(self.value) < len(other.value))
+
+ def __gt__(self, other):
+ return QLBoolean(len(self.value) > len(other.value))
+
+ def __le__(self, other):
+ return QLBoolean(len(self.value) <= len(other.value))
+
+ def __ge__(self, other):
+ return QLBoolean(len(self.value) >= len(other.value))
+
+ def __add__(self, other):
+ return QLString(self.value + other.value)
+
+ def get_json_value(self):
+ return self.value
+
+ @staticmethod
+ def get_literal_node(value):
+ return StringNode(None, QLString, value)
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return LineEdit()
diff --git a/ql/types/type.py b/ql/types/type.py
new file mode 100644
index 0000000..912946d
--- /dev/null
+++ b/ql/types/type.py
@@ -0,0 +1,3 @@
+class QLType:
+ def __init__(self):
+ pass
diff --git a/ql/types/undefined.py b/ql/types/undefined.py
new file mode 100644
index 0000000..2deafe0
--- /dev/null
+++ b/ql/types/undefined.py
@@ -0,0 +1,40 @@
+from gui.widgets.label import Label
+from ql.ast.nodes.expressions.literals.undefined_literal import UndefinedNode
+from ql.types.boolean import QLBoolean
+from ql.types.type import QLType
+
+
+class QLUndefined(QLType):
+ def __init__(self, *unused):
+ super(QLUndefined, self).__init__()
+ self.__value = None
+
+ @property
+ def value(self):
+ return self.__value
+
+ def __bool__(self):
+ return False
+
+ def __repr__(self):
+ return 'Undefined'
+
+ def __eq__(self, other):
+ if isinstance(other, QLUndefined):
+ return QLBoolean(self.value == other.value)
+
+ return QLBoolean(False)
+
+ def __ne__(self, other):
+ return QLBoolean(not self == other)
+
+ def get_json_value(self):
+ return self.value
+
+ @staticmethod
+ def get_literal_node(unused):
+ return UndefinedNode(None, QLUndefined, QLUndefined(None))
+
+ @staticmethod
+ def pyqt5_default_widget():
+ return Label('Undefined')