Jelajahi Sumber

Migrate VCAT classes from IVProg to its own repo

Lucas de Souza 1 tahun lalu
melakukan
67a0013263
100 mengubah file dengan 19806 tambahan dan 0 penghapusan
  1. 3 0
      .babelrc
  2. 3 0
      .eslintignore
  3. 39 0
      .eslintrc.json
  4. 39 0
      .gitignore
  5. 14 0
      .vscode/launch.json
  6. 9 0
      .vscode/settings.json
  7. 7 0
      README.md
  8. TEMPAT SAMPAH
      css/fonts/NimbusSanLConBold.ttf
  9. TEMPAT SAMPAH
      css/fonts/NimbusSanLConRegular.ttf
  10. TEMPAT SAMPAH
      css/fonts/cyrillic-ext-roboto.woff2
  11. TEMPAT SAMPAH
      css/fonts/cyrillic-roboto.woff2
  12. TEMPAT SAMPAH
      css/fonts/greek-ext-roboto.woff2
  13. TEMPAT SAMPAH
      css/fonts/greek-roboto.woff2
  14. TEMPAT SAMPAH
      css/fonts/latin-ext-roboto.woff2
  15. TEMPAT SAMPAH
      css/fonts/latin-roboto.woff2
  16. TEMPAT SAMPAH
      css/fonts/texgyreheros-regular.otf
  17. TEMPAT SAMPAH
      css/fonts/vietnamese-roboto.woff2
  18. 121 0
      css/ivprog-assessment.css
  19. 3 0
      css/ivprog-editor.css
  20. 208 0
      css/ivprog-term.css
  21. 1164 0
      css/ivprog-visual-1.0.css
  22. 56 0
      css/roboto.css
  23. 372 0
      css/semantic.min.css
  24. TEMPAT SAMPAH
      css/themes/default/assets/fonts/brand-icons.eot
  25. 1008 0
      css/themes/default/assets/fonts/brand-icons.svg
  26. TEMPAT SAMPAH
      css/themes/default/assets/fonts/brand-icons.ttf
  27. TEMPAT SAMPAH
      css/themes/default/assets/fonts/brand-icons.woff
  28. TEMPAT SAMPAH
      css/themes/default/assets/fonts/brand-icons.woff2
  29. TEMPAT SAMPAH
      css/themes/default/assets/fonts/icons.eot
  30. TEMPAT SAMPAH
      css/themes/default/assets/fonts/icons.otf
  31. 1518 0
      css/themes/default/assets/fonts/icons.svg
  32. TEMPAT SAMPAH
      css/themes/default/assets/fonts/icons.ttf
  33. TEMPAT SAMPAH
      css/themes/default/assets/fonts/icons.woff
  34. TEMPAT SAMPAH
      css/themes/default/assets/fonts/icons.woff2
  35. TEMPAT SAMPAH
      css/themes/default/assets/fonts/outline-icons.eot
  36. 366 0
      css/themes/default/assets/fonts/outline-icons.svg
  37. TEMPAT SAMPAH
      css/themes/default/assets/fonts/outline-icons.ttf
  38. TEMPAT SAMPAH
      css/themes/default/assets/fonts/outline-icons.woff
  39. TEMPAT SAMPAH
      css/themes/default/assets/fonts/outline-icons.woff2
  40. TEMPAT SAMPAH
      css/themes/default/assets/images/flags.png
  41. 105 0
      grammar/en/ivprog.ts
  42. 268 0
      grammar/es/ivprog.g4
  43. 36 0
      grammar/es/langFunctions.js
  44. 10 0
      grammar/es/langLibs.js
  45. 10 0
      grammar/helper.ts
  46. 11 0
      grammar/index.ts
  47. 224 0
      grammar/lexer.ts
  48. 105 0
      grammar/pt/ivprog.ts
  49. 5 0
      i18n/csv.d.ts
  50. 137 0
      i18n/error.csv
  51. 20 0
      i18n/index.ts
  52. 12 0
      i18n/message.csv
  53. 177 0
      i18n/ui.csv
  54. 34 0
      i18n_csv_loader.js
  55. 115 0
      karma.conf.js
  56. 39 0
      main.js
  57. 10445 0
      package-lock.json
  58. 57 0
      package.json
  59. 88 0
      src/assessment/ivprogAssessment.js
  60. 240 0
      src/assessment/output_matching/assessment_result.js
  61. 181 0
      src/assessment/output_matching/output_matching.js
  62. 22 0
      src/assessment/output_matching/output_result.js
  63. 47 0
      src/ast/ASA.txt
  64. 11 0
      src/ast/ast_helpers.js
  65. 10 0
      src/ast/commands/arrayAssign.js
  66. 14 0
      src/ast/commands/arrayDeclaration.js
  67. 10 0
      src/ast/commands/assign.js
  68. 8 0
      src/ast/commands/break.js
  69. 25 0
      src/ast/commands/case.js
  70. 14 0
      src/ast/commands/command.js
  71. 16 0
      src/ast/commands/commandBlock.js
  72. 12 0
      src/ast/commands/declaration.js
  73. 17 0
      src/ast/commands/for.js
  74. 18 0
      src/ast/commands/formalParameter.js
  75. 43 0
      src/ast/commands/function.js
  76. 11 0
      src/ast/commands/ifThenElse.js
  77. 37 0
      src/ast/commands/index.js
  78. 13 0
      src/ast/commands/repeatUntil.js
  79. 10 0
      src/ast/commands/return.js
  80. 19 0
      src/ast/commands/switch.js
  81. 12 0
      src/ast/commands/sysCall.js
  82. 18 0
      src/ast/commands/while.js
  83. 16 0
      src/ast/error/syntaxError.js
  84. 193 0
      src/ast/error/syntaxErrorFactory.js
  85. 30 0
      src/ast/expressions/arrayAccess.js
  86. 101 0
      src/ast/expressions/arrayLiteral.js
  87. 20 0
      src/ast/expressions/boolLiteral.js
  88. 19 0
      src/ast/expressions/charLiteral.js
  89. 23 0
      src/ast/expressions/expression.js
  90. 45 0
      src/ast/expressions/functionCall.js
  91. 25 0
      src/ast/expressions/index.js
  92. 22 0
      src/ast/expressions/infixApp.js
  93. 20 0
      src/ast/expressions/intLiteral.js
  94. 9 0
      src/ast/expressions/literal.js
  95. 20 0
      src/ast/expressions/realLiteral.js
  96. 19 0
      src/ast/expressions/stringLiteral.js
  97. 18 0
      src/ast/expressions/unaryApp.js
  98. 18 0
      src/ast/expressions/variableLiteral.js
  99. 1572 0
      src/ast/ivprogParser.js
  100. 0 0
      src/ast/operators.ts

+ 3 - 0
.babelrc

@@ -0,0 +1,3 @@
+{
+  "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties"]
+}

+ 3 - 0
.eslintignore

@@ -0,0 +1,3 @@
+# /js/visualUI/
+/js/Sortable.js
+/js/iassign-integration-functions.js

+ 39 - 0
.eslintrc.json

@@ -0,0 +1,39 @@
+{
+  "env": {
+    "browser": true,
+    "es6": true,
+    "node": true
+  },
+  "parser": "@typescript-eslint/parser",
+  "plugins": ["@typescript-eslint"],
+  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
+  "globals": {
+    "Atomics": "readonly",
+    "SharedArrayBuffer": "readonly"
+  },
+  "parserOptions": {
+    "ecmaVersion": 2018,
+    "sourceType": "module"
+  },
+  "rules": {
+    "camelcase": "off",
+    "no-unused-vars": "off",
+    "@typescript-eslint/no-unused-vars": [
+      "error",
+      { "argsIgnorePattern": "^_" }
+    ],
+    "@typescript-eslint/camelcase": "off",
+    "space-before-function-paren": "off",
+    "@typescript-eslint/space-before-function-paren": ["error", "always"]
+  },
+  "overrides": [
+    {
+      "files": ["*.js", "*.jsx"],
+      "rules": {
+        "@typescript-eslint/explicit-member-accessibility": 0,
+        "@typescript-eslint/explicit-function-return-type": 0
+      }
+    }
+  ]
+}
+

+ 39 - 0
.gitignore

@@ -0,0 +1,39 @@
+#compiled files
+/build
+/dist
+.ima_version.json
+ivprog.tar.gz
+vcat*.tgz
+# dependencies
+/node_modules
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+grammar/**/.antlr/
+
+# System Files
+.DS_Store
+Thumbs.db
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json

+ 14 - 0
.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Launch Program",
+            "program": "${workspaceFolder}/build/ivprog.bundle.js"
+        }
+    ]
+}

+ 9 - 0
.vscode/settings.json

@@ -0,0 +1,9 @@
+{
+  "editor.tabSize": 2,
+  "files.watcherExclude": {
+    "**/.git/objects/**": true,
+    "**/.git/subtree-cache/**": true,
+    "**/node_modules/**": true
+  },
+  "javascript.format.insertSpaceBeforeFunctionParenthesis": true
+}

+ 7 - 0
README.md

@@ -0,0 +1,7 @@
+# VCAT - Visual Code Assessment Tool
+
+VCAT is an code interpreter with automatic assessment designed to provide Visual Programming Languages with automatic assessment capabilities
+
+# How to integrate your visual language with VCAT?
+
+TODO

TEMPAT SAMPAH
css/fonts/NimbusSanLConBold.ttf


TEMPAT SAMPAH
css/fonts/NimbusSanLConRegular.ttf


TEMPAT SAMPAH
css/fonts/cyrillic-ext-roboto.woff2


TEMPAT SAMPAH
css/fonts/cyrillic-roboto.woff2


TEMPAT SAMPAH
css/fonts/greek-ext-roboto.woff2


TEMPAT SAMPAH
css/fonts/greek-roboto.woff2


TEMPAT SAMPAH
css/fonts/latin-ext-roboto.woff2


TEMPAT SAMPAH
css/fonts/latin-roboto.woff2


TEMPAT SAMPAH
css/fonts/texgyreheros-regular.otf


TEMPAT SAMPAH
css/fonts/vietnamese-roboto.woff2


+ 121 - 0
css/ivprog-assessment.css

@@ -0,0 +1,121 @@
+@font-face {
+  font-family: 'NimbusSanLConRegular';
+  src: url(fonts/NimbusSanLConRegular.ttf) format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'NimbusSanLConBold';
+  src: url(fonts/NimbusSanLConBold.ttf) format('truetype');
+  font-weight: bold;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'TeXGyreHerosRegular';
+  src: url(fonts/texgyreheros-regular.otf) format('opentype');
+  font-weight: normal;
+  font-style: normal;
+}
+body {
+  font-family: 'TeXGyreHerosRegular';
+  background-color: #b9c7ca;
+  margin-left: 2rem;
+}
+.details-body > .details-header > h2 {margin-bottom: 0.5rem;}
+.details-body > .details-header > p {
+  padding-left: 1rem;
+  margin: 0;
+}
+table td { font-size: 14pt;}
+.stringdiff-delete, .stringdiff-insert {font-weight: bold;}
+.stringdiff-insert, .assessment-input-read {color: #22a222}
+.stringdiff-delete {
+  text-decoration: line-through;
+  color: #d02929
+}
+.details-body h3 {
+  margin-top: 0.5rem;
+  margin-bottom: 0.5rem;
+}
+.detaisl-div-table {
+  padding-left: 1rem;
+  margin-top: 1rem;
+}
+.assessment-output-table {
+  border-collapse: collapse;
+  border-style: hidden;
+}
+.assessment-output-table tr:nth-child(odd) {background: #CCC}
+.assessment-output-table tr:nth-child(even) {background: #f7f2c9}
+.assessment-output-table tr > th {
+  background-color: #000;
+  color: #fff;
+  font-family: 'NimbusSansLBoldCond';
+  font-weight: bold;
+  font-style: normal; 
+  letter-spacing: .05rem;
+}
+.assessment-output-table td, .assessment-output-table th {
+  border-left: 1px solid black;
+  padding: 0.5rem;
+  text-align: center;
+  max-width: 16rem;
+  font-family: 'NimbusSanLConRegular';
+  vertical-align: middle;
+  letter-spacing: .05rem;
+}
+.assessment-string-expected, .assessment-string-generated, .assessment-string-diff {text-align: left;}
+p.assessment-failed-execution {padding-left: 1rem;}
+.assessment-failed-case {
+  color:#FF1212;
+  padding-right: 1rem;
+}
+.assessment-input-unread {color: #d02929}
+.assessment-number-result-failed, .assessment-bool-result-failed {color: #d02929}
+.assessment-number-result, .assessment-bool-result, .assessment-string-result {color: #22a222}
+.assessment-popup {
+  position: relative;
+  display: inline-block;
+  cursor: pointer;
+}
+.assessment-popup .assessment-popuptext {
+  visibility: hidden;
+  width: 160px;
+  background-color: #555;
+  color: #fff;
+  text-align: center;
+  border-radius: 6px;
+  padding: 8px 0;
+  position: absolute;
+  z-index: 1;
+  bottom: 125%;
+  left: 50%;
+  margin-left: -80px;
+}
+.assessment-popup .assessment-popuptext::after {
+  content: "";
+  position: absolute;
+  top: 100%;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 5px;
+  border-style: solid;
+  border-color: #555 transparent transparent transparent;
+}
+.assessment-popup:hover .assessment-popuptext {
+  visibility: visible;
+  -webkit-animation: fadeIn 1s;
+  animation: fadeIn 1s;
+}
+@-webkit-keyframes fadeIn {
+  from {opacity: 0;} 
+  to {opacity: 1;}
+}
+@keyframes fadeIn {
+  from {opacity: 0;}
+  to {opacity:1 ;}
+}
+.assessment-empty-output {
+  height: 1.5rem;
+  width: 1.5rem;
+}

+ 3 - 0
css/ivprog-editor.css

@@ -0,0 +1,3 @@
+.CodeMirror {
+  height: 100% !important;
+}

+ 208 - 0
css/ivprog-term.css

@@ -0,0 +1,208 @@
+.ivprog-term-div {
+  /* background-color: black; */
+  width: 100%;
+  height: 12rem;
+  overflow-y: scroll;
+}
+
+#ivprog-term-div {
+  z-index: 10;
+}
+
+.ivprog-term-userText {
+  white-space: pre;
+  height: 1.6rem;
+}
+
+.ivprog-term-userText, .ivprog-term-userInput {
+  color: #f2d6d6;
+  height: 1.6rem;
+}
+
+.ivprog-term-info {
+  color: #28a628;
+  height: 1.6rem;
+}
+
+.ivprog-term-error {
+  color: #df4242;
+  height: 1.6rem;
+}
+
+.ivprog-term-input {
+  font-family: 'Courier New', Courier, monospace;
+  font-weight: 500;
+  background-color: inherit;
+  border: 0;
+  color: white;
+}
+
+.ivprog-term-div > .ivprog-term-input, .ivprog-term-div > .ivprog-term-userText,
+.ivprog-term-div > .ivprog-term-info, .ivprog-term-div, .ivprog-term-error {
+  padding-left: 20px;
+}
+
+#ivprog-term {
+  /* border: 1px solid gray;
+  background: black;
+  margin-top: -30px;
+  position: relative;
+  padding: 5px;
+  z-index: 999; */
+}
+/* #ivprog-term i {
+  margin-left: 5px;
+  cursor: pointer;
+} */
+.div_toggle_console {
+  cursor: pointer;
+}
+.ivprog-term-active {
+  box-shadow: 0 0 5px rgba(81, 203, 238, 1) !important;
+  border: 3px solid rgba(81, 203, 238, 1) !important;
+}
+
+.ivprog-term-div {
+  overflow:scroll;
+}
+
+.ivprog-term-div::-webkit-scrollbar {
+    width: 12px;
+}
+
+.ivprog-term-div::-webkit-scrollbar-track {
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
+    -webkit-border-radius: 10px;
+    border-radius: 10px;
+}
+
+.ivprog-term-div::-webkit-scrollbar-thumb {
+    -webkit-border-radius: 10px;
+    border-radius: 10px;
+    background: green;
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
+}
+
+/**novas regras bash*/
+#ivprog-terminal-inputdiv {
+  padding-left: 12px;
+}
+#ivprog-console-clearbtn, #ivprog-console-showbtn, #ivprog-console-hidebtn {
+  cursor: pointer;
+}
+
+.bash {
+  box-shadow: 0 0 30px rgba(0,0,0,0.4);
+  border-radius: 3px;
+  font-family: "Andale Mono", Consolas, "Courier New" !important;
+}
+
+.bash-title {
+  text-align: center;
+  color: #525252;
+  padding: 5px 0;
+  margin: 0;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
+  font-size: 0.85em;
+  border: 1px solid #CCCCCC;
+  border-bottom: none;
+
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+
+  background: #f7f7f7; /* Old browsers */
+  background: linear-gradient(to bottom,  #f7f7f7 0%,#B8B8B8 100%); /* W3C */
+}
+
+.bash-body {
+  /* margin: 0;
+  padding: 5px; */
+  background: #111010;
+  /* list-style: none; */
+  color: #F8F8FF;
+
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+  border: 1px solid #CCCCCC;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+
+.bash-text {
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+}
+
+.bash-highlight {
+  color: #45D40C;
+}
+
+.bash-highlight a {
+  color: #45D40C;
+  text-decoration: underline;
+}
+
+/* .bash-body li:before {
+  content: '$';
+  color: #F8F8FF;
+  position: absolute;
+  left: 0;
+  top: 0;
+} */
+
+.bash-body i {
+  cursor: text;
+}
+
+.bash-body li {
+  word-wrap: break-word;
+  position: relative;
+  padding: 0 0 0 15px;
+}
+
+#cmd {
+  font-family: courier;
+  font-size: 14px;
+  line-height: normal;
+  background:inherit;
+  color: #21f838;
+  padding: 5px;
+  overflow: hidden;
+}
+#cmd span {
+  float: left;
+  padding-left: 3px;
+  white-space: pre;
+}
+#cursor {
+  float: left;
+  width: 5px;
+  height: 14px;
+  background: #21f838;
+}
+#cmd ~ input {
+  width: 0;
+  height: 0;
+  opacity: 0;
+}
+
+.ivprog-term-error > span > ul {
+  margin:0 !important;
+}
+
+.ivprog-term-error > span > ul > li {
+  padding: 0;
+  margin: 0;
+  line-height: 1rem;
+}
+
+.assessment-div-detail:hover {
+  cursor: pointer;
+}
+.assessment-div-detail:hover > span {
+  text-decoration: underline;
+}
+
+.bash span {
+  font-family: 'Courier New', Courier, monospace;
+}

File diff ditekan karena terlalu besar
+ 1164 - 0
css/ivprog-visual-1.0.css


+ 56 - 0
css/roboto.css

@@ -0,0 +1,56 @@
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/cyrillic-ext-roboto.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/cyrillic-roboto.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/greek-ext-roboto.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/greek-roboto.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/vietnamese-roboto.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/latin-ext-roboto.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/latin-roboto.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}

File diff ditekan karena terlalu besar
+ 372 - 0
css/semantic.min.css


TEMPAT SAMPAH
css/themes/default/assets/fonts/brand-icons.eot


File diff ditekan karena terlalu besar
+ 1008 - 0
css/themes/default/assets/fonts/brand-icons.svg


TEMPAT SAMPAH
css/themes/default/assets/fonts/brand-icons.ttf


TEMPAT SAMPAH
css/themes/default/assets/fonts/brand-icons.woff


TEMPAT SAMPAH
css/themes/default/assets/fonts/brand-icons.woff2


TEMPAT SAMPAH
css/themes/default/assets/fonts/icons.eot


TEMPAT SAMPAH
css/themes/default/assets/fonts/icons.otf


File diff ditekan karena terlalu besar
+ 1518 - 0
css/themes/default/assets/fonts/icons.svg


TEMPAT SAMPAH
css/themes/default/assets/fonts/icons.ttf


TEMPAT SAMPAH
css/themes/default/assets/fonts/icons.woff


TEMPAT SAMPAH
css/themes/default/assets/fonts/icons.woff2


TEMPAT SAMPAH
css/themes/default/assets/fonts/outline-icons.eot


File diff ditekan karena terlalu besar
+ 366 - 0
css/themes/default/assets/fonts/outline-icons.svg


TEMPAT SAMPAH
css/themes/default/assets/fonts/outline-icons.ttf


TEMPAT SAMPAH
css/themes/default/assets/fonts/outline-icons.woff


TEMPAT SAMPAH
css/themes/default/assets/fonts/outline-icons.woff2


TEMPAT SAMPAH
css/themes/default/assets/images/flags.png


+ 105 - 0
grammar/en/ivprog.ts

@@ -0,0 +1,105 @@
+import {
+  I18N_LEXER_TYPES,
+  I18N_LEXER_COMMANDS,
+  I18N_LEXER_BOOLVAL,
+  I18N_LEXER_LOGICOP,
+  makeLexer,
+  I18N_LANG_LIBS,
+  I18N_LANG_FUNCS,
+} from "../lexer";
+
+// i18n lexer strings for the language.
+const types: I18N_LEXER_TYPES = {
+  // types
+  RK_REAL: "real",
+  RK_INTEGER: "int",
+  RK_BOOLEAN: "bool",
+  RK_CHARACTER: "char",
+  RK_STRING: "string",
+};
+const commands: I18N_LEXER_COMMANDS = {
+  // RK_VOID is not formally part of Types since it doesn't have a valid value/instance
+  RK_VOID: "vazio",
+  // commands
+  RK_PROGRAM: "program",
+  RK_SWITCH: "switch",
+  RK_CASE: "case",
+  RK_DEFAULT: "otherwise",
+  RK_CONST: "const",
+  RK_FUNCTION: "function",
+  RK_RETURN: "return",
+  RK_FOR: "for",
+  RK_FOR_ALT: "repeat_for",
+  RK_FOR_FROM: "from",
+  RK_FOR_TO: "to",
+  RK_FOR_PASS: "pass",
+  RK_BREAK: "break",
+  RK_DO: "repeat",
+  RK_DO_UNTIL: "until",
+  RK_WHILE: "while",
+  RK_WHILE_ALT: "repeat_while",
+  RK_IF: "if",
+  RK_ELSE: "else",
+  RK_REFERENCE: "&",
+};
+const boolVal: I18N_LEXER_BOOLVAL = {
+  RK_FALSE: "false",
+  RK_TRUE: "true",
+};
+
+const logicOp: I18N_LEXER_LOGICOP = {
+  RK_LOGICAL_NOT: "not",
+  RK_LOGICAL_AND: "AND",
+  RK_LOGICAL_OR: "OR",
+};
+
+const langLibs: I18N_LANG_LIBS = {
+  $mathLib: "Mathematics",
+  $ioLib: "IO",
+  $strLib: "Text",
+  $arrayLib: "Array",
+  $langLib: "Conversion",
+};
+
+const langFuncs: I18N_LANG_FUNCS = {
+  main_function: "main",
+  $read: "read",
+  $write: "write",
+  $numElements: "total_of_elements",
+  $matrixLines: "total_of_lines",
+  $matrixColumns: "total_of_columns",
+  $substring: "substring",
+  $length: "length",
+  $uppercase: "uppercase",
+  $lowercase: "lowercase",
+  $charAt: "char_at",
+  $isReal: "is_real",
+  $isInt: "is_integer",
+  $isBool: "is_logic",
+  $castReal: "to_real",
+  $castInt: "to_integer",
+  $castBool: "to_logic",
+  $castString: "to_string",
+  $castChar: "to_char",
+  $sin: "sin",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "sqrt",
+  $pow: "pow",
+  $log: "log",
+  $abs: "abs",
+  $negate: "negate",
+  $invert: "invert",
+  $max: "maximum",
+  $min: "minimum",
+  $rand: "random",
+};
+// END i18n lexer strings
+export const enLexer = makeLexer({
+  commands,
+  boolVal,
+  logicOp,
+  types,
+  langLibs,
+  langFuncs,
+});

+ 268 - 0
grammar/es/ivprog.g4

@@ -0,0 +1,268 @@
+lexer grammar ivprog;
+
+// BEGIN i18n Lexical rules
+RK_PROGRAM
+  : 'program'
+  ;
+
+RK_REAL
+  : 'real'
+  ;
+
+RK_VOID
+  : 'void'
+  ;
+
+RK_BOOLEAN
+  : 'bool'
+  ;
+
+RK_STRING
+  : 'string'
+  ;
+
+RK_INTEGER
+  : 'int'
+  ;
+
+RK_CHARACTER
+  : 'char'
+  ;
+
+RK_SWITCH
+  : 'switch'
+  ;
+
+RK_CASE
+  : 'case'
+  ;
+
+RK_DEFAULT
+  : 'otherwise'
+  ;
+
+RK_CONST
+  : 'const'
+  ;
+
+RK_FUNCTION
+  : 'function'
+  ;
+
+RK_RETURN
+  : 'return'
+  ;
+
+RK_FOR
+  : 'for'
+  ;
+
+RK_FOR_ALT
+  : 'repeat_for'
+  ;
+
+RK_FOR_FROM
+  : 'from'
+  ;
+
+RK_FOR_TO
+  : 'to'
+  ;
+
+RK_FOR_PASS
+  : 'pass'
+  ;
+
+RK_BREAK
+  : 'break'
+  ;
+
+RK_DO
+  : 'repeat'
+  ;
+
+RK_DO_UNTIL
+  : 'until'
+  ;
+
+RK_WHILE
+  : 'while'
+  ;
+
+RK_WHILE_ALT
+  : 'repeat_while'
+  ;
+
+RK_IF
+  : 'if'
+  ;
+
+RK_ELSE
+  : 'else'
+  ;
+
+RK_FALSE
+  : 'false'
+  ;
+
+RK_TRUE
+  : 'true'
+  ;
+
+fragment RK_LOGICAL_NOT
+  : 'not'
+  ;
+
+fragment RK_LOGICAL_AND
+  : 'AND'
+  ;
+
+fragment RK_LOGICAL_OR
+  : 'OR'
+  ;
+
+RK_REFERENCE
+  : '&'
+  ;
+// END i18n Lexical rules
+
+// GAMBIARRA   : '.' |'á'| 'à'| 'ã'|'â'|'é'|'ê'|'í'|'ó'|'ô'|'õ'|'ú'|'ü'|'ç'|'Ä'|'À'|'Ã'|'Â'|'É'|'Ê'|'Ë'|'Ó'|'Ô'|'Õ'|'Ú'|'Ü'|'Ç'|'#'|'$'|'"'|'§'|'?'|'¹'|'²'|'³'|'£'|'¢'|'¬'|'ª'|'º'|'~'|'\''|'`'|'\\'|'@';
+
+OPEN_PARENTHESIS
+  : '('
+  ;
+
+CLOSE_PARENTHESIS
+  : ')'
+  ;
+
+OPEN_BRACE
+  : '['
+  ;
+
+CLOSE_BRACE
+  : ']'
+  ;
+
+OPEN_CURLY
+  : '{'
+  ;
+
+CLOSE_CURLY
+  : '}'
+  ;
+
+COMMA
+  : ','
+  ;
+
+EQUAL
+  : '<-'
+  | '←'
+  ;
+
+SUM_OP
+  : ('+'|'-')
+  ;
+
+MULTI_OP
+  : ('*'|'/'|'%')
+  ;
+
+AND_OPERATOR
+  : RK_LOGICAL_AND
+  ;
+
+OR_OPERATOR
+  : RK_LOGICAL_OR
+  ;
+
+RELATIONAL_OPERATOR
+  : ('>='|'=='|'<='|'>'|'<'|'!=')
+  ;
+
+COLON
+  : ':'
+  ;
+
+NOT_OPERATOR
+  : RK_LOGICAL_NOT
+  ;
+
+ID
+  : [a-zA-Z_] [a-zA-Z0-9_]*
+  ;
+
+LIB_ID
+  : ID '.' ID
+  ;
+
+INTEGER
+  : [0-9]+
+  | ('0x'|'0X')(HEX_DIGIT)+
+  | ('0b'|'0B')[0-1]+
+  ;
+
+REAL
+  : [0-9]+ '.' [0-9]+
+  | [0-9]+ '.' [0-9]* ExponentPart
+  ;
+
+fragment ExponentPart
+  : [eE] [+-]? [0-9]+
+  ;
+
+STRING
+  : '"' STRING_CHARACTER* '"'
+  ;
+
+fragment STRING_CHARACTER //String as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
+  : ~["\\\r\n]
+  | ESC_SEQ
+  ;
+
+CHARACTER //Character as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
+  : '\'' ( ESC_SEQ | ~['\\\r\n]) '\''
+  ;
+
+WHITESPACE
+  : ( ' ' | '\t') -> skip
+  ;
+
+fragment SEMICOLON
+  : ';'
+  ;
+
+EOS
+  : [\r\n]+
+  | SEMICOLON
+  ;
+
+fragment HEX_DIGIT
+  : [0-9a-fA-F]
+  ;
+
+fragment OCTAL_DIGIT
+  : [0-7]
+  ;
+
+fragment ESC_SEQ
+  : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\''|'\\')
+  | ESC_UNICODE
+  | ESC_OCTAL
+  ;
+
+fragment ESC_OCTAL
+  : '\\' [0-3] OCTAL_DIGIT OCTAL_DIGIT
+  | '\\' OCTAL_DIGIT OCTAL_DIGIT
+  | '\\' OCTAL_DIGIT
+  ;
+
+fragment ESC_UNICODE
+  : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+  ;
+
+COMMENTS
+  : ('//' ~('\n'|'\r')* '\r'? '\n'
+    | '/*' .*? '*/') -> channel(HIDDEN)
+  ;

+ 36 - 0
grammar/es/langFunctions.js

@@ -0,0 +1,36 @@
+/* This is a dictionary of the language defined functions
+**/
+export default {
+  main_function: "main",
+  $read: "read",
+  $write: "write",
+  $numElements: "total_of_elements",
+  $matrixLines: "total_of_lines",
+  $matrixColumns: "total_of_columns",
+  $substring: "substring",
+  $length: "length",
+  $uppercase: "uppercase",
+  $lowercase: "lowercase",
+  $charAt: "char_at",
+  $isReal: "is_real",
+  $isInt: "is_integer",
+  $isBool: "is_logic",
+  $castReal: "to_real",
+  $castInt: "to_integer",
+  $castBool: "to_logic",
+  $castString: "to_string",
+  $castChar: "to_char",
+  $sin: "sin",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "sqrt",
+  $pow: "pow",
+  $log: "log",
+  $abs: "abs",
+  $negate: "negate",
+  $invert: "invert",
+  $max: "maximum",
+  $min: "minimum",
+  $rand: "random"
+
+}

+ 10 - 0
grammar/es/langLibs.js

@@ -0,0 +1,10 @@
+/**
+ * This is the dictionary of the language defined libraries
+ */
+export default {
+  $mathLib: "Mathematic",
+  $ioLib: "IO",
+  $strLib: "Text",
+  $arrayLib: "Array",
+  $langLib: "Conversion"
+}

+ 10 - 0
grammar/helper.ts

@@ -0,0 +1,10 @@
+export function combineRegex(strings: TemplateStringsArray, ...pieces: any[]) {
+  return new RegExp(
+    strings.raw
+      .map(
+        (r, i) =>
+          r + (pieces[i] === undefined ? "" : "(?:" + pieces[i].source + ")")
+      )
+      .join("")
+  );
+}

+ 11 - 0
grammar/index.ts

@@ -0,0 +1,11 @@
+import { ptLexer as pt } from "./pt/ivprog";
+import { enLexer as en } from "./en/ivprog";
+import { IVProgLexer } from "./lexer";
+/*import * as ES from "./es/ivprog.g4";
+import ESFuncs from "./es/langFunctions";
+import ESLibs from "./es/langLibs";*/
+const lexers: Record<string, IVProgLexer> = {};
+lexers["pt"] = pt;
+lexers["en"] = en;
+
+export default lexers;

+ 224 - 0
grammar/lexer.ts

@@ -0,0 +1,224 @@
+import * as moo from "moo";
+import { combineRegex } from "./helper";
+
+export interface I18N_LEXER_TYPES {
+  RK_INTEGER: string;
+  RK_REAL: string;
+  RK_CHARACTER: string;
+  RK_STRING: string;
+  RK_BOOLEAN: string;
+}
+
+export interface I18N_LEXER_BOOLVAL {
+  RK_FALSE: string;
+  RK_TRUE: string;
+}
+
+export interface I18N_LEXER_LOGICOP {
+  RK_LOGICAL_NOT: string;
+  RK_LOGICAL_AND: string;
+  RK_LOGICAL_OR: string;
+}
+
+export interface I18N_LEXER_COMMANDS {
+  RK_PROGRAM: string;
+  RK_VOID: string;
+  RK_SWITCH: string;
+  RK_CASE: string;
+  RK_DEFAULT: string;
+  RK_CONST: string;
+  RK_FUNCTION: string;
+  RK_RETURN: string;
+  RK_FOR: string;
+  RK_FOR_ALT: string;
+  RK_FOR_FROM: string;
+  RK_FOR_TO: string;
+  RK_FOR_PASS: string;
+  RK_BREAK: string;
+  RK_DO: string;
+  RK_DO_UNTIL: string;
+  RK_WHILE: string;
+  RK_WHILE_ALT: string;
+  RK_IF: string;
+  RK_ELSE: string;
+  RK_REFERENCE: string;
+}
+
+export interface I18N_LANG_LIBS {
+  $ioLib: string;
+  $strLib: string;
+  $mathLib: string;
+  $langLib: string;
+  $arrayLib: string;
+}
+
+export interface I18N_LANG_FUNCS {
+  main_function: string;
+  $read: string;
+  $write: string;
+  $numElements: string;
+  $matrixLines: string;
+  $matrixColumns: string;
+  $substring: string;
+  $length: string;
+  $uppercase: string;
+  $lowercase: string;
+  $charAt: string;
+  $isReal: string;
+  $isInt: string;
+  $isBool: string;
+  $castReal: string;
+  $castInt: string;
+  $castBool: string;
+  $castString: string;
+  $castChar: string;
+  $sin: string;
+  $cos: string;
+  $tan: string;
+  $sqrt: string;
+  $pow: string;
+  $log: string;
+  $abs: string;
+  $negate: string;
+  $invert: string;
+  $max: string;
+  $min: string;
+  $rand: string;
+}
+
+export interface I18nLexer {
+  commands: I18N_LEXER_COMMANDS;
+  logicOp: I18N_LEXER_LOGICOP;
+  boolVal: I18N_LEXER_BOOLVAL;
+  types: I18N_LEXER_TYPES;
+  langLibs: I18N_LANG_LIBS;
+  langFuncs: I18N_LANG_FUNCS;
+}
+
+export class IVProgLexer {
+  constructor (
+    private RKs: Record<string, string>,
+    public lexer: moo.Lexer,
+    private rules: I18N_LEXER_RULES,
+    private i18nLexer: I18nLexer
+  ) {}
+
+  getReservedKeys (): Record<string, string> {
+    return this.RKs;
+  }
+
+  getRules (): I18N_LEXER_RULES {
+    return this.rules;
+  }
+
+  getTypeKeys (): I18N_LEXER_TYPES {
+    return this.i18nLexer.types;
+  }
+
+  getLangLibs (): I18N_LANG_LIBS {
+    return this.i18nLexer.langLibs;
+  }
+
+  getLangFuncs (): I18N_LANG_FUNCS {
+    return this.i18nLexer.langFuncs;
+  }
+}
+
+export interface I18N_LEXER_RULES
+  extends I18N_LEXER_TYPES,
+    I18N_LEXER_COMMANDS,
+    I18N_LEXER_BOOLVAL,
+    I18N_LEXER_LOGICOP {
+  OPEN_BRACE: string;
+  CLOSE_BRACE: string;
+  OPEN_PARENTHESIS: string;
+  CLOSE_PARENTHESIS: string;
+  OPEN_CURLY: string;
+  CLOSE_CURLY: string;
+  COMMA: string;
+  ASSIGNMENT: string;
+  REAL: string;
+  INTEGER: string;
+  SUM_OP: string;
+  MULTI_OP: string;
+  RELATIONAL_OPERATOR: string;
+  COLON: string;
+  STRING: string;
+  CHARACTER: string;
+  EOS: string;
+  WHITESPACE: string;
+  COMMENTS: string;
+  RK_REFERENCE: string;
+  ID: string;
+  DOT: string;
+  ERROR: string;
+}
+
+// General Regex Rules
+const ID = "[a-zA-Z_][a-zA-Z0-9_]*";
+const HEX_DIGIT = "[0-9a-fA-F]";
+const OCTAL_DIGIT = "[0-7]";
+const ESC_OCTAL = RegExp(
+  `\\\\[0-3]${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}`
+);
+const ESC_UNICODE = RegExp(
+  `\\\\u${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}`
+);
+const ESC_SEQ_BASE = /\\[b,t,n,f,r,",',\\]|/;
+const ESC_SEQ = combineRegex`${ESC_SEQ_BASE}|${ESC_UNICODE}|${ESC_OCTAL}`;
+const STRING_CHARACTER = combineRegex`${ESC_SEQ}|[^"\\\\]`;
+
+export function makeLexer (lexer: I18nLexer): IVProgLexer {
+  const RKs: Record<string, string> = {};
+  const rules: Record<string, string> = {};
+  Object.entries(lexer.types).forEach(([key, value]) => {
+    RKs[key] = value;
+    rules[key] = key;
+  });
+  Object.entries(lexer.boolVal).forEach(([key, value]) => {
+    RKs[key] = value;
+    rules[key] = key;
+  });
+  Object.entries(lexer.commands).forEach(([key, value]) => {
+    RKs[key] = value;
+    rules[key] = key;
+  });
+  RKs["RK_LOGICAL_AND"] = lexer.logicOp.RK_LOGICAL_AND;
+  RKs["RK_LOGICAL_OR"] = lexer.logicOp.RK_LOGICAL_OR;
+  RKs["RK_LOGICAL_NOT"] = lexer.logicOp.RK_LOGICAL_NOT;
+
+  rules["RK_LOGICAL_AND"] = "RK_LOGICAL_AND";
+  rules["RK_LOGICAL_OR"] = "RK_LOGICAL_OR";
+  rules["RK_LOGICAL_NOT"] = "RK_LOGICAL_NOT";
+
+  const RESERVED_KEYS = moo.keywords(RKs);
+
+  const lexerRules: moo.Rules = {
+    COMMENTS: { match: /\/\/[^$]*?$|\/\*[^$]*?\*\//, lineBreaks: true },
+    OPEN_BRACE: /\[/,
+    CLOSE_BRACE: /\]/,
+    OPEN_PARENTHESIS: /\(/,
+    CLOSE_PARENTHESIS: /\)/,
+    OPEN_CURLY: /\{/,
+    CLOSE_CURLY: /\}/,
+    COMMA: /,/,
+    ASSIGNMENT: /<-|←/,
+    REAL: /[0-9]+\.[0-9]*[eE][+-]?[0-9]+|[0-9]+\.[0-9]+/,
+    INTEGER: RegExp(`(?:0x|0X)${HEX_DIGIT}+|(?:0b|0B)[0-1]+|[0-9]+`),
+    SUM_OP: /[+-]/,
+    MULTI_OP: /[*/%]/,
+    RELATIONAL_OPERATOR: />=|==|<=|>|<|!=/,
+    COLON: /:/,
+    STRING: combineRegex`"(?:${STRING_CHARACTER})*?"`,
+    CHARACTER: combineRegex`'(?:${ESC_SEQ}|[^'\\\\])'`,
+    EOS: { match: /;\r?\n?|[\r\n]+/, lineBreaks: true },
+    WHITESPACE: /(?: |\t)+/,
+    RK_REFERENCE: RegExp(lexer.commands.RK_REFERENCE),
+    ID: { match: RegExp(ID), type: RESERVED_KEYS },
+    DOT: /\./,
+    ERROR: { match: /[\$?`]/, error: true },
+  };
+  Object.entries(lexerRules).forEach(([key, _]) => (rules[key] = key));
+  const moolexer = moo.compile(lexerRules);
+  return new IVProgLexer(RKs, moolexer, rules as unknown as I18N_LEXER_RULES, lexer);
+}

+ 105 - 0
grammar/pt/ivprog.ts

@@ -0,0 +1,105 @@
+import {
+  I18N_LEXER_TYPES,
+  I18N_LEXER_COMMANDS,
+  I18N_LEXER_BOOLVAL,
+  I18N_LEXER_LOGICOP,
+  makeLexer,
+  I18N_LANG_LIBS,
+  I18N_LANG_FUNCS,
+} from "../lexer";
+
+// i18n lexer strings for the language.
+const types: I18N_LEXER_TYPES = {
+  // types
+  RK_REAL: "real",
+  RK_INTEGER: "inteiro",
+  RK_BOOLEAN: "logico",
+  RK_CHARACTER: "caractere",
+  RK_STRING: "cadeia",
+};
+const commands: I18N_LEXER_COMMANDS = {
+  // RK_VOID is not formally part of Types since it doesn't have a valid value/instance
+  RK_VOID: "vazio",
+  // commands
+  RK_PROGRAM: "programa",
+  RK_SWITCH: "escolha",
+  RK_CASE: "caso",
+  RK_DEFAULT: "contrario",
+  RK_CONST: "const",
+  RK_FUNCTION: "funcao",
+  RK_RETURN: "devolva",
+  RK_FOR: "para",
+  RK_FOR_ALT: "repita_para",
+  RK_FOR_FROM: "de",
+  RK_FOR_TO: "ate",
+  RK_FOR_PASS: "passo",
+  RK_BREAK: "pare",
+  RK_DO: "repita",
+  RK_DO_UNTIL: "ate_que",
+  RK_WHILE: "enquanto",
+  RK_WHILE_ALT: "repita_enquanto",
+  RK_IF: "se",
+  RK_ELSE: "senao",
+  RK_REFERENCE: "&",
+};
+const boolVal: I18N_LEXER_BOOLVAL = {
+  RK_FALSE: "falso",
+  RK_TRUE: "verdadeiro",
+};
+
+const logicOp: I18N_LEXER_LOGICOP = {
+  RK_LOGICAL_NOT: "nao",
+  RK_LOGICAL_AND: "E",
+  RK_LOGICAL_OR: "OU",
+};
+
+const langLibs: I18N_LANG_LIBS = {
+  $mathLib: "Matematica",
+  $ioLib: "ES",
+  $strLib: "Texto",
+  $arrayLib: "Arranjo",
+  $langLib: "Conversao",
+};
+
+const langFuncs: I18N_LANG_FUNCS = {
+  main_function: "inicio",
+  $read: "leia",
+  $write: "escreva",
+  $numElements: "total_de_elementos",
+  $matrixLines: "total_de_linhas",
+  $matrixColumns: "total_de_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "caractere_na_posicao",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $castChar: "como_caractere",
+  $sin: "seno",
+  $cos: "cosseno",
+  $tan: "tangente",
+  $sqrt: "raiz_quadrada",
+  $pow: "potencia",
+  $log: "logaritmo",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo",
+  $rand: "numero_aleatorio",
+};
+// END i18n lexer strings
+export const ptLexer = makeLexer({
+  commands,
+  boolVal,
+  logicOp,
+  types,
+  langLibs,
+  langFuncs,
+});

+ 5 - 0
i18n/csv.d.ts

@@ -0,0 +1,5 @@
+declare module "*.csv" {
+  const content: {[id: string]: unknown};
+  export default content;
+}
+

File diff ditekan karena terlalu besar
+ 137 - 0
i18n/error.csv


+ 20 - 0
i18n/index.ts

@@ -0,0 +1,20 @@
+import * as Messages from './message.csv';
+import * as UI from './ui.csv';
+import * as Errors from './error.csv';
+
+type Dict =  {[id: string]: unknown};
+
+const MessagesObj = Messages as Dict;
+const UIObj = UI as Dict;
+const ErrorsObj = Errors as Dict;
+const i18n_data = {} as Dict;
+
+for (const key in UIObj) {
+  const data = {} as Dict;
+  data['error'] = ErrorsObj[key];
+  data['message'] = MessagesObj[key];
+  data['ui'] = UIObj[key];
+  i18n_data[key] = data;
+}
+
+export default i18n_data;

+ 12 - 0
i18n/message.csv

@@ -0,0 +1,12 @@
+id,pt,en,es
+test_case_success,"<div class='assessment-div-detail' onClick='ivprogCore.openAssessmentDetail(event)' data-page=""$1""><span>Caso de teste $0</span>: OK</div>","<div class='assessment-div-detail' onClick='ivprogCore.openAssessmentDetail(event)' data-page=""$1""><span>Test case $0</span>: OK</div>","<div class='assessment-div-detail' onClick='ivprogCore.openAssessmentDetail(event)' data-page=""$1""><span>Test case $0</span>: OK</div>"
+test_case_duration,Levou $0ms,Took $0ms,Tardó $0ms
+test_suite_grade,A sua solução alcançou $0% da nota.,Your solution scored $0% of the grade.,Su solución obtuvo $0% de la calificación.
+awaiting_input_message,O seu programa está em execução e aguardando uma entrada! Digite algo e pressione ENTER...,Your program is running and awaiting for an input. Type something and press ENTER…,Su programa se está ejecutando y esperando una entrada. Escriba algo y presione ENTER ...
+assessment-empty-expected-tooltip,A saída gerada foi além do esperado,The generated output was beyond the amount expected,The generated output was beyond the amount expected
+assessment-empty-generated-tooltip,O programa não gerou saídas suficientes,The program did not generate enough outputs,El programa no generó suficientes resultados.
+testcase_autogen_unused_input,A solução submetida não lê todas entradas disponíveis no caso de teste 1,The submitted solution does not read all inputs available in the test case $0,La solución presentada no lee todas las entradas disponibles en el caso de prueba 1
+testcase_autogen_empty,Sua solução não gerou qualquer saída para o caso de teste $0.,Your solution did not generate any output for test case $0.,Su solución no generó ningún resultado para el caso de prueba de $ 0.
+success_execution,Execução do programa finalizada!,Program execution finished!,¡Ejecución del programa terminada!
+aborted_execution,A execução do programa foi interrompida!,Program execution was aborted!,¡La ejecución del programa fue abortada!
+unexpected_execution_error,Erro inesperado durante a execução do programa.,Unexpected error during program execution.,Error inesperado durante la ejecución del programa.

+ 177 - 0
i18n/ui.csv

@@ -0,0 +1,177 @@
+id,pt,en,es
+function,funcao,function,function
+btn_clear,Limpar,Clean,Limpiar
+btn_function,Função,Function,Funcíon
+btn_arithmetic_plus,Adição,Addition,Adición
+btn_arithmetic_minus,Subtração,Subtraction,Sustracción
+btn_arithmetic_multiplication,Multiplicação,Multiplication,Multiplicación
+btn_arithmetic_division,Divisão,Division,División
+btn_arithmetic_module,Módulo,Remainder,Resto
+btn_break,Pare,break,break
+btn_case,Caso,Case,Caso
+btn_add_var,Adicionar variável,Add a variable,Add a variable
+btn_drag_and_drop_function,Mover função,Move function,Mover función
+btn_delete_function,Excluir função,Delete function,Borrar función
+expression_invalid,Expressão inválida. Verifique a sintáxe antes de continuar.,Invalid expression. Check the syntax before proceeding.,Expresión no válida. Verifique la sintaxis antes de continuar.
+expression_undelcared_variable,Variáveis não declaradas:,Undeclared variables:,Variables no declaradas:
+expression_undeclared_function,Funções não definidas:,Undefined functions:,Funcíon no declaradas:
+start,inicio,main,main
+type_void,vazio,void,void
+type_integer,inteiro,int,int
+logic_operator_and,E,AND,AND
+logic_operator_or,OU,OR,OR
+logic_operator_not,nao,not,not
+type_real,real,real,real
+program,programa,program,program
+type_text,cadeia,string,string
+textvar_default_value,texto,text,texto
+type_boolean,logico,bool,bool
+logic_value_true,verdadeiro,true,true
+logic_value_false,falso,false,false
+variable,Variável,Variable,Variable
+command,Comando,Command,Comando
+new_parameter,parametro,parameter,parametro
+new_variable,variavel,variable,variable
+new_global,global,global,global
+new_function,nova_funcao,new_function,nueva_función
+matrix,matriz,matrix,matriz
+vector,vetor,vector,vector
+text_lock_expression,Bloquear expressão,Block expression,Expresión de bloque
+text_unlock_expression,Desbloquear expressão,Unlock expression,Desbloquear expresión
+text_edit_expression,Editar expressão manualmente,Edit expression manually,Editar expresión manualmente
+text_edit_expression_confirm,Confirmar edição,Confirm edition,Confirmar edición
+text_edit_expression_cancel,Cancelar edição,Cancel edition,Cancelar edición
+text_add_function,Adicionar uma nova função ao programa,Add a new function to the program,Agregar una nueva función al programa
+text_move_command,Mover comando,Move command,Mover comando
+text_add_parameters,Adicionar um novo parâmetro,Add a new parameter,Agregar un nuevo parámetro
+text_parameter_reference,Definir parâmetro como passagem por referência,Define parameter passed by reference,Define parameter passed by reference
+text_parameter_copy,Definir parâmetro como passagem por cópia,Define parameter passed by copy,Define parameter passed by copy
+text_comment_start,Comentário inicial da função...,Function initial comment,Comentario inicial de la función
+text_comment_main,Esta é a função principal...,This is the main funcion,Esta es la función principal
+text_read_var,Entrada/Leitura de dados,Input/Read data,Entrada/Lectura de dados
+text_write_var,Saída/Escrita de dados,Output/Write data,Salida/Escribir datos
+text_command_read,leia,read,read
+text_command_write,escreva,write,write
+text_return,devolva,return,return
+text_btn_return,Devolver,Return,Devolución
+text_comment,Comentário,Comment,Comentario
+string_join_or,ou,or,or
+matrix_info_string,matriz de $0,matrix of $0,matriz de $0
+vector_info_string,vetor de $0,vector of $0,vector de $0
+text_attribution,Atribuição,Assignment,Asignación
+text_if,se,if,if
+text_break,pare,break,break
+text_else,senao,else,else
+text_for,repita_para,repeat_for,repeat_for
+text_code_while,repita_enquanto,repeat_while,repeat_while
+text_code_do,repita,repeat,repeat
+text_code_do_until,ate_que,until,until
+text_command_do,repita,repeat,repeat
+text_command_while,repita enquanto,repeat while,repeat while
+text_command_do_until,até que,until,until
+text_code_switch,escolha,switch,switch
+text_code_case,caso,case,case
+text_config_programming,Programação,Programming,Programación
+text_config_programming_both,Visual e textual,Visual & Textual,Visual & Textual
+text_config_programming_textual,Textual,Textual,Textual
+text_config_programming_visual,Visual,Visual,Visual
+text_logic_expression,Lógicos,Logic,Lógicos
+text_arithmetic_expression,Aritméticos,Arithmetics,Aritmética
+text_iftrue,Se condição senão,If condition else,Si condicion sino
+text_message_error_activity_file,Aconteceu um erro ao processar a atividade. <br> Recarregue a página para tentar novamente.,There was an error processing the activity.<br> Reload the page to try again.,Se produjo un error al procesar la actividad.<br> Recargar la página para volver a intentarlo.
+text_message_error_upload_file,Não foi possível carregar o arquivo.<br>Verifique o conteúdo do arquivo e tente novamente.,It was not possible upload the file.<br>Verify the file's content and try again.,text_message_error_upload_file
+text_message_error_upload_close,Fechar,Close,Close
+text_message_error_activity_reload,Recarregar,Reload,Recargar
+text_repeatNtimes,Repita N vezes,Repeat N times,Repetir N veces
+text_receives,recebe,receives,receives
+text_whiletrue,Enquanto verdadeiro,While true,Mientras verdad
+text_dowhiletrue,Repita até que verdadeiro,Repeat until true,Repita hasta verdad
+text_switch,Escolha,Switch,Switch
+text_functioncall,Chamada de função,Function call,Llamada de función
+text_value,Valor,Value,Valor
+text_operator,Operador,Operator,Operador
+text_parentheses,Parênteses,Parentheses,Paréntesis
+text_change,Alterar,Modify,Modify
+text_teacher_algorithm,Algoritmo,Algorithm,Algorithm
+text_teacher_algorithm_include,Incluir o algoritmo abaixo no exercício,Include the algorithm below in the activity,Incluir el algoritmo en la actividad.
+text_teacher_test_case,Casos de teste,Test cases,Test cases
+text_teacher_config,Configurações,Configurations,Configuraciones
+text_teacher_data_types,Tipos de dados,Data types,Data types
+text_teacher_commands,Comandos,Commands,Commands
+text_teacher_functions,Funções,Functions,Funciones
+text_teacher_create_functions,Criar novas funções,Create new functions,Create new functions
+text_teacher_create_movement_functions,Movimentar funções,Move functions,Move functions
+text_teacher_test_case_input,Entrada,Input,Input
+text_teacher_test_case_output,Saída,Output,Output
+text_teacher_test_case_actions,Ações,Actions,Actions
+text_teacher_test_case_add,Adicionar caso de teste,Add test case,Add test case
+text_header_ivprog_functions,Funções do iVProg,iVProg Functions,iVProg Functions
+text_menu_functions_math,Matemática,Math,Math
+text_menu_functions_text,Texto,Text,Text
+text_menu_functions_array,Arranjo,Array,Array
+text_menu_functions_conversion,Conversão,Conversion,Conversion
+text_no_variable,Nenhuma variável declarada,No variable declared,No variable declared
+text_no_variable_instruction,"Antes de utilizar uma variável, é necessário criá-la","Before using a variable, you need to create it","Antes de usar una variable, debe crearla"
+text_ivprog_description,Programação Visual interativa na Internet,Interactive and Visual Programming on the Internet,Interactive and Visual Programming on the Internet
+tooltip_visual,Programação visual,Visual programming,Visual programming
+tooltip_textual,Programação textual,Textual programming,Textual programming
+tooltip_upload,Upload de código fonte,Upload source code,Upload source code
+tooltip_download,Download do código fonte,Download source code,Download source code
+tooltip_undo,Desfazer,Undo,Undo
+tooltip_redo,Refazer,Redo,Redo
+tooltip_run,Executar o programa,Run the program,Run the program
+tooltip_evaluate,Avaliar o programa,Evaluate the program,Evaluate the program
+tooltip_help,Ajuda,Help,Help
+tooltip_add_global,Adicionar variável global,Add a global variable,Add a global variable
+tooltip_hide_function,Ocultar os elementos da função,Hide function elements,Hide function elements
+var_menu_select_var,Selecione uma variável,Select a variable,Select a variable
+var_menu_select_all,Selecione,Select,Select
+var_menu_select_function,Selecione uma função,Select a function,Select a function
+expression_menu_select,Construir uma expressão lógica,Construct a logic expression,Construct a logic expression
+inform_valid_content,Informe o conteúdo!,Provide some data,Proporcionar algunos datos
+inform_valid_expression,Construa uma expressão lógica!,Construct a logic expression,Construct a logic expression
+tooltip_terminal_clear,Limpa o terminal removendo todos os textos já escritos e os pendentes.,Clears the terminal by removing all wrriten and pending text.,Borra el terminal eliminando todo el texto escrito y pendiente.
+tooltip_terminal_show,Exibe o terminal caso esteja escondido,Shows the terminal if it is hidden,Muestra el terminal si está oculto.
+tooltip_terminal_hide,Esconde o terminal caso não esteja escondido,Hides the terminal if it is not on display,Oculta el terminal si no está en exhibición
+tooltip_menu_read,Comando para receber dados pelo teclado,Command to input data from keyboard,Command to input data from keyboard
+tooltip_menu_write,Comando para apresentar conteúdo ao usuário,Command to present content to user,Command to present content to user
+tooltip_menu_comments,Bloco para comentários internos do programador,Block to comments from developer,Block to comments from developer
+tooltip_menu_attribution,Comando para atribuir uma expressão a uma variável,Command to assign an expression to a variable,Command to assign an expression to a variable
+tooltip_menu_call_function,Comando para realizar a chamada de uma função,Command to execute a function call,Command to execute a function call
+tooltip_menu_if_else,Estrutura para que os comandos só sejam executados de acordo com as condições estabelecidas,Structure in which command only run when the conditions are satisfied,Structure in which command only run when the conditions are satisfied
+tooltip_menu_repeat_n_times,Estrutura para executar um bloco de comandos repetidamente,Structure to execute a block of commands repeatedly,Structure to execute a block of commands repeatedly
+tooltip_menu_repeat_whiletrue,Estrutura para repetir um bloco de comandos enquanto a condição for verdadeira,Structure to execute a block repeatdly while condition is true,Structure to execute a block repeatdly while condition is true
+tooltip_menu_repeat_dowhiletrue,Estrutura que executa um bloco e o repete enquanto a condição for verdadeira,Structure that executes a block and repeat while the condition is true,Structure that executes a block and repeat while the condition is true
+tooltip_menu_repeat_switch,Estrutura de escolha do bloco a ser executado,Structure that choices the block to be executed,Structure that choices the block to be executed
+tooltip_menu_repeat_return,Comando para devolver o resultado e finalizar a função,Command to return the result and finish the function,Command to return the result and finish the function
+tooltip_move_var,Mover variável,Move variable,Move variable
+tooltip_remove_var,Excluir variável,Delete variable,Delete variable
+text_ivprog_version,Versão,Version,Version
+text_teacher_filter,Filtro,Filter,Filter
+text_teacher_filter_active,Ativado,Activated,Activated
+text_teacher_filter_help,"Ao ativar o filtro, as modificações do iVProg estarão bloqueadas.",By activating the filter modifications in iVProg will be blocked,"Al activar el filtro, las modificaciones en iVProg serán bloqueadas"
+text_join_assessment_outputs, ; , ; , ;
+assessment-detail-time-label,Duração,Duration,Duration
+assessment-detail-grade-label,Nota,Grade,Grade
+assessment-detail-input-label,Entradas,Inputs,Inputs
+assessment-detail-output-label,Saídas,Outputs,Outputs
+assessment-detail-expected-label,Esperava,Expected,Expected
+assessment-detail-generated-label,Gerou,Generated,Generated
+assessment-detail-result-label,Correção,Correction,Correction
+assessment-detail-title,Caso de Teste $0,Test Case $0,Test Case $0
+text_teacher_generate_outputs,Gerar saídas,Generate outputs,Generate outputs
+text_teacher_generate_outputs_algorithm,"Antes de gerar as saídas, elabore um algoritmo!",Before generating the outputs you need to create an algorithm,Antes de generar las salidas necesita crear un algoritmo
+text_code_for_from,de,from,from
+text_code_for_to,ate,to,to
+text_code_for_pass,passo,pass,pass
+text_for_from,de,from,from
+text_for_to,até,to,to
+text_for_pass,passo,pass,pass
+text_relational_expression,Relacionais,Relational,Relational
+write_command_newline_on,Quebra de linha ativada, Line break is on,El salto de línea está activado
+write_command_newline_off, Quebra de linha desativada, Line break is off,El salto de línea está desactivado
+write_seprator_menu_text,Espaço,Spacer,Spacer
+initial_program_code,programa {\n\n\t\tfuncao vazio inicio () {\n\t\t\t// Inicie seu codigo aqui!\n\t\t}\n},program {\n\n\t\tfunction void main () {\n\t\t\t// Start your code here!\n\t\t}\n},program {\n\n\t\tfunction void main () {\n\t\t\t// Start your code here!\n\t\t}\n}
+type_char,caractere,char,char
+charvar_default_value,A,A,A
+write_seprator_menu_tooltip,Separador para imprimir mais valores/variáveis,Separator used to print more values/variables,Separator used to print more values/variables

+ 34 - 0
i18n_csv_loader.js

@@ -0,0 +1,34 @@
+const Readable = require("stream").Readable;
+const csv = require("csv-parser");
+
+function createStream (text) {
+  const stream = new Readable();
+  stream.push(text);
+  stream.push(null);
+  return stream;
+}
+
+module.exports = function (csv_data) {
+  const callback = this.async();
+  let csv_headers = [];
+  const file_data = []
+  const stream = createStream(csv_data);
+  stream.pipe(csv())
+  .on('error', error => callback(error))
+  .on('headers', headers => csv_headers = headers)
+  .on('data', data => file_data.push(data))
+  .on('end', () => {
+    const id = csv_headers[0];
+    const messages = {};
+    for(let i = 1; i < csv_headers.length; i += 1) {
+      const lang = csv_headers[i];
+      const strings = {};
+      file_data.forEach( data => {
+        strings[data[id]] = data[lang];
+      });
+      messages[lang] = strings;
+    }
+    callback(null, `module.exports = ${JSON.stringify(messages)}`);
+  })
+}
+

+ 115 - 0
karma.conf.js

@@ -0,0 +1,115 @@
+process.env.CHROME_BIN = '/snap/bin/chromium';
+ 
+module.exports = function(config) {
+  config.set({
+    //root path location to resolve paths defined in files and exclude
+    basePath: '',
+    //files/patterns to exclude from loaded files
+    exclude: [],
+    //files/patterns to load in the browser
+    files: [
+     'tests/*.spec.js'
+      /*parameters*/
+          //watched: if autoWatch is true all files that have set watched to true will be watched for changes
+          //served: should the files be served by Karma's webserver?
+          //included: should the files be included in the browser using <script> tag?
+          //nocache: should the files be served from disk on each request by Karma's webserver?
+      /*assets*/
+          //{pattern: '*.html', watched:true, served:true, included:false}
+          //{pattern: 'images/*', watched:false, served:true, included:false}      
+    ],
+    
+    //executes the tests whenever one of watched files changes
+    autoWatch: false,
+    //if true, Karma will run tests and then exit browser
+    singleRun: true,
+    //if true, Karma fails on running empty test-suites
+    failOnEmptyTestSuite:false,
+    //reduce the kind of information passed to the bash
+    logLevel: config.LOG_WARN, //config.LOG_DISABLE, config.LOG_ERROR, config.LOG_INFO, config.LOG_DEBUG
+                                      
+    //list of frameworks you want to use, only jasmine is installed automatically
+    frameworks: ['jasmine'],
+    //list of browsers to launch and capture
+    browsers: ['ChromeHeadless'/*,'PhantomJS','Firefox','Edge','ChromeCanary','Opera','IE','Safari'*/],
+    //list of reporters to use
+    reporters: ['mocha' /*,'kjhtml','dots','progress','spec'*/],
+    
+    //address that the server will listen on, '0.0.0.0' is default
+    listenAddress: '0.0.0.0',
+    //hostname to be used when capturing browsers, 'localhost' is default
+    hostname: 'localhost',
+    //the port where the web server will be listening, 9876 is default
+    port: 9876,
+    //when a browser crashes, karma will try to relaunch, 2 is default
+    retryLimit:0,
+    //how long does Karma wait for a browser to reconnect, 2000 is default
+    browserDisconnectTimeout: 5000,
+    //how long will Karma wait for a message from a browser before disconnecting from it, 10000 is default
+    browserNoActivityTimeout: 60000,
+    //timeout for capturing a browser, 60000 is default
+    captureTimeout: 60000,
+ 
+    client: {
+      //capture all console output and pipe it to the terminal, true is default
+      captureConsole:false,
+      //if true, Karma clears the context window upon the completion of running the tests, true is default
+      clearContext:false,
+      //run the tests on the same window as the client, without using iframe or a new window, false is default
+      runInParent: false,
+      //true: runs the tests inside an iFrame; false: runs the tests in a new window, true is default
+      useIframe:true,
+      jasmine:{
+        //tells jasmine to run specs in semi random order, false is default
+        random: false
+      }
+    },
+ 
+    /*karma-webpack config*/
+    //pass your webpack configuration for karma
+    webpack: {
+      node: {
+        fs: 'empty',
+      },
+      module: {
+        rules: [
+            {
+              test: /\.js$/,
+              exclude: /(node_modules)/,
+              use: {
+                loader: "babel-loader",
+                options: {
+                  presets: ["@babel/preset-env"]
+                }
+              }
+            },
+            {
+              test: /\.g4$/,
+              exclude: /(node_modules)/,
+              use: {
+                loader:'antlr4-webpack-loader'
+              }
+            }
+        ]
+    },
+    },
+    preprocessors: {
+      //use webpack to support require() in test-suits .js files
+      //use babel-loader from webpack to compile es2015 features in .js files
+      //add webpack as preprocessor
+      'tests/*.spec.js': ['webpack']
+    },
+    webpackMiddleware: {
+      //turn off webpack bash output when run the tests
+      noInfo: true,
+      stats: {
+        chunks: false
+      }
+    },
+ 
+    /*karma-mocha-reporter config*/
+    mochaReporter: {
+      output: 'full'  //full, autowatch, minimal
+    }
+  });
+};

+ 39 - 0
main.js

@@ -0,0 +1,39 @@
+import { Config } from "./src/util/config";
+import { i18nHelper } from "./src/services/i18nHelper";
+import * as LocalizedStringsService from "./src/services/localizedStringsService";
+import { openAssessmentDetail, levenshteinDistance } from "./src/util/utils";
+import { processData } from "./src/util/dataProcess";
+import { parseExpression, parseCode } from "./src/util/parseFromVisual";
+import { autoGenerateTestCaseOutput } from "./src/util/auto_gen_output";
+import { IVProgProcessor } from "./src/processor/ivprogProcessor.js";
+import { SemanticAnalyser } from "./src/processor/semantic/semanticAnalyser.js";
+import { Modes } from "./src/processor/modes";
+import { Location } from "./src/memory/location";
+
+const Settings = {
+  programming: [],
+  functions: [],
+  datatypes: [],
+  commands: [],
+  filter: []
+}
+
+const i18n = i18nHelper.i18n;
+const LocalizedStrings = LocalizedStringsService.getInstance();
+
+export {
+  i18n,
+  Settings,
+  Config,
+  LocalizedStrings,
+  SemanticAnalyser,
+  IVProgProcessor,
+  Modes,
+  Location,
+  openAssessmentDetail,
+  autoGenerateTestCaseOutput,
+  parseExpression,
+  parseCode,
+  levenshteinDistance,
+  processData,
+};

File diff ditekan karena terlalu besar
+ 10445 - 0
package-lock.json


+ 57 - 0
package.json

@@ -0,0 +1,57 @@
+{
+  "name": "vcat",
+  "version": "0.1.0",
+  "description": "Visual Code Assessment Tool",
+  "main": "./dist/main.js",
+  "scripts": {
+    "build": "webpack --mode=development",
+    "watch": "webpack --watch --mode=development",
+    "compile": "webpack --mode=production",
+    "publish": "npm run compile && npm pack",
+    "test": "./node_modules/karma/bin/karma start"
+  },
+  "exports": {
+    ".": "./main.js"
+  },
+  "files": [
+    "dist/**/*.*"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git+http://200.144.254.107/git/LInE/vcat"
+  },
+  "keywords": [
+    "programação",
+    "ensino",
+    "visual"
+  ],
+  "author": "LInE-IME/USP",
+  "license": "MIT",
+  "bugs": {
+    "url": "http://200.144.254.107/git/LInE/vcat/issues"
+  },
+  "homepage": "http://200.144.254.107/git/LInE/vcat#readme",
+  "devDependencies": {
+    "@babel/core": "^7.10.2",
+    "@babel/plugin-proposal-class-properties": "^7.18.6",
+    "@babel/plugin-transform-runtime": "^7.10.1",
+    "@babel/preset-env": "^7.10.2",
+    "@babel/preset-typescript": "^7.10.1",
+    "@babel/register": "^7.18.9",
+    "@types/moo": "^0.5.5",
+    "@typescript-eslint/eslint-plugin": "^5.7.0",
+    "@typescript-eslint/parser": "^5.0.0",
+    "babel-loader": "^8.0.6",
+    "csv-parser": "^2.3.3",
+    "eslint": "^8.5.0",
+    "typescript": "^3.9.5",
+    "webpack": "5.x",
+    "webpack-cli": "5.x"
+  },
+  "dependencies": {
+    "@babel/runtime": "^7.10.2",
+    "decimal.js": "^10.2.0",
+    "line-i18n": "git+http://200.144.254.107/git/LInE/line-i18n.git",
+    "moo": "^0.5.1"
+  }
+}

+ 88 - 0
src/assessment/ivprogAssessment.js

@@ -0,0 +1,88 @@
+import line_i18n from 'line-i18n'
+import { IVProgProcessor } from "./../processor/ivprogProcessor";
+import { DOMConsole} from "./../io/domConsole";
+import * as LocalizedStringsService from "../services/localizedStringsService";
+import { OutputMatching } from './output_matching/output_matching';
+import { Config } from '../util/config';
+
+
+const LocalizedStrings = LocalizedStringsService.getInstance();
+
+const StringTypes = line_i18n.StringTypes;
+
+const AssessmentConfig = {
+  max_instruction_count: 350250,
+  suspend_threshold: 200
+}
+
+export class IVProgAssessment {
+
+  constructor (ast_code, testCases, domConsole) {
+    this.ast_code = ast_code;
+    this.testCases = testCases;
+    this.domConsole = domConsole;
+    this.old_config = JSON.parse(JSON.stringify(Config));
+    Config.setConfig(AssessmentConfig);
+  }
+
+  runTest () {
+    try {
+      // loop test cases and show messages through domconsole
+      const partialTests = this.testCases.map( (t, name) => {
+        return new OutputMatching(new IVProgProcessor(this.ast_code), t.input, t.output, name);
+      });
+      const testResult = partialTests.map(om => om.eval());
+      return Promise.all(testResult).then(results => {
+        let grade = 0;
+        for(let i = 0; i < results.length; i += 1) {
+          const result = results[i];
+          grade += result.grade;
+          if(result.grade == 1) {
+            this.writeToConsole(DOMConsole.INFO, StringTypes.MESSAGE,'test_case_success',
+              result.name + 1, result.generateOutput());
+          } else if (result.status == 1) {
+            this.writeToConsole(DOMConsole.ERR, StringTypes.ERROR,'test_case_failed_exception',
+              result.name + 1, result.error_msg, result.generateOutput());
+          } else {
+            this.writeToConsole(DOMConsole.ERR, StringTypes.ERROR,'test_case_failed',
+              result.name + 1, result.generateOutput());
+          }
+        }
+        grade /= results.length;
+        const channel = grade == 1 ? DOMConsole.INFO : DOMConsole.ERR;
+        this.writeToConsole(channel, StringTypes.MESSAGE, "test_suite_grade", (grade * 100).toFixed(2));
+        return grade;
+      });
+      // return testResult.then(function (total) {
+      //   const grade = total / this.testCases.length;
+      //   const channel = grade == 1 ? DOMConsole.INFO : DOMConsole.ERR;
+      //   this.writeToConsole(channel, StringTypes.MESSAGE, "test_suite_grade", (grade * 100).toFixed(2));
+      //   return Promise.resolve(grade)
+      // }).catch(err => {
+      //   this.domConsole.err("Erro inesperado durante o cálculo da nota.");// try and show error messages through domconsole
+      //   this.domConsole.err(err.message);
+      //   return Promise.resolve(0);
+      // });
+    } catch (error) {
+      this.showErrorMessage(DOMConsole.ERR, StringTypes.MESSAGE, "unexpected_execution_error");
+      this.domConsole.err(error.message);
+      return Promise.resolve(0);
+    } finally {
+      Config.setConfig(this.old_config);
+    }
+  }
+
+  showErrorMessage (errorID, ...args) {
+    this.domConsole.err(LocalizedStrings.getError(errorID, args));
+  }
+
+  showInfoMessage (msgID, ...args) {
+    this.domConsole.info(LocalizedStrings.getMessage(msgID, args));
+  }
+
+  writeToConsole (channel, msgType, msgID, ...args) {
+    let msg = LocalizedStrings.getString(msgID, msgType);
+    msg = LocalizedStrings.processString(msg, args);
+    this.domConsole.writeRawHTML(msg, channel);
+  }
+}

+ 240 - 0
src/assessment/output_matching/assessment_result.js

@@ -0,0 +1,240 @@
+import StringDiff from "./../../util/string_diff";
+import { LocalizedStrings } from './../../services/localizedStringsService'
+
+export class OutputAssessmentResult {
+
+  static get PAGE_TEMPLATE () {
+    return `<!DOCTYPE html>
+    <html>
+      <head>
+        <meta http-equiv='content-type' content='text/html; charset=UTF-8'>
+        <link rel='stylesheet' href='css/ivprog-assessment.css' type='text/css'/>
+      </head>
+    <body>
+      :assessment-result:
+    </body>
+    </html>`;
+  }
+
+  static get DETAIL_TEMPLATE () {
+    return `<div class='details-body'>
+        <div class='details-header'>
+          <h2>:test-name:</h2>
+          <p>:time-label:: <span>:time:ms</span></p>
+          <p>:grade-label:: <span>:grade:%</span></p>
+        </div>
+        <div>
+          <h3>:input-label:</h3>
+          <ul>
+            <li>:input-list:</li>
+          </ul>
+        </div>
+        <div>
+          <h3>:output-label:</h3>
+          :output-result:
+        </div>
+      </div>`;
+  }
+
+  static get OUPUT_TABLE_TEMPLATE () {
+    return `<div class='detaisl-div-table'>
+        <table class='assessment-output-table'>
+          <tr>
+            <th>:expected-label:</th>
+            <th>:generated-label:</th>
+            <th>:result-label:</th>
+          </tr>
+          :results:
+        </table>
+      </div>`;
+  }
+
+  static get OUTPUT_TEMPLATE () {
+    return `<tr><td class=':class-expected:'>$0</td>
+            <td class=':class-generated:'>$1</td>
+            <td class=':class-result:'>$2</td></tr>`;
+  }
+
+  static get EMPTY_OUTPUT_TEMPLATE () {
+    return `<div class='assessment-popup'><img class='assessment-empty-output' src='img/empty.svg'>
+      <span class='assessment-popuptext'>$0</span></div>`;
+  }
+
+  static get FAILED_TEMPLATE () {
+    return `<p class='assessment-failed-execution'><span class='assessment-failed-case'>✗</span>$0</p>`;
+  }
+
+  static get INPUT_INFO_TEMPLATE () {
+    return `<span class='$0'>$1</span>`;
+  }
+
+  // Status code - it is not grade related!
+  // 0 - Succesful execution
+  // 1 - failed execution
+  constructor (name, status, inputs, result, store, time, error_msg = '') {
+    this.name = name;
+    this.status = status;
+    this.inputs = inputs;
+    this.results = result;
+    this.store = store;
+    this.time = time;
+    this.error_msg = error_msg;
+  }
+
+  get grade () {
+    if(this.results == null) {
+      return 0;
+    }
+    return this.results.reduce((prev, val) => prev + val.grade, 0) / this.results.length;
+  }
+
+  prepareResults () {
+    let template = OutputAssessmentResult.DETAIL_TEMPLATE;
+    const grade = (this.grade * 100).toFixed(2);
+    const time = this.time || "-";
+    template = template.replace(':test-name:', LocalizedStrings.getUI('assessment-detail-title', [this.name + 1]));
+    template = template.replace(':time-label:', LocalizedStrings.getUI('assessment-detail-time-label'));
+    template = template.replace(':time:', time);
+    template = template.replace(':grade-label:', LocalizedStrings.getUI('assessment-detail-grade-label'));
+    template = template.replace(':grade:', grade);
+    const input_spans = this.prepareInputList(this.inputs);
+    template = template.replace(':input-label:', LocalizedStrings.getUI('assessment-detail-input-label'));
+    template = template.replace(':input-list:', input_spans);
+    template = template.replace(':output-label:', LocalizedStrings.getUI('assessment-detail-output-label'));
+    if(this.status == 0) {
+      const output_rows = this.results.map(result => {
+        if(result.type == "string") {
+          return this.formatString(result);
+        } else if (result.type == "number") {
+          return this.formatNumber(result);
+        } else {
+          return this.formatBool(result);
+        }
+      }, this);
+      template = template.replace(':output-result:', this.prepareOutputTable(output_rows));
+    } else {
+      let failed_text =  OutputAssessmentResult.FAILED_TEMPLATE;
+      failed_text = failed_text.replace("$0", this.error_msg);
+      template = template.replace(":output-result:", failed_text);
+    }
+    return template;
+  }
+
+  prepareInputList (input_list) {
+    const list = input_list.map(input => {
+      let template = OutputAssessmentResult.INPUT_INFO_TEMPLATE;
+      template = template.replace("$1", input.value);
+      if(input.read) {
+        template = template.replace("$0", "assessment-input-read");
+      } else {
+        template = template.replace("$0", "assessment-input-unread");
+      }
+      return template;
+    }, this);
+    return list.join(LocalizedStrings.getUI('text_join_assessment_outputs'));
+  }
+
+  prepareOutputTable (output_rows) {
+    let template = OutputAssessmentResult.OUPUT_TABLE_TEMPLATE;
+    template = template.replace(':expected-label:', LocalizedStrings.getUI('assessment-detail-expected-label'));
+    template = template.replace(':generated-label:', LocalizedStrings.getUI('assessment-detail-generated-label'));
+    template = template.replace(':result-label:', LocalizedStrings.getUI('assessment-detail-result-label'));
+    template = template.replace(':results:', output_rows.join(''));
+    return template;
+  }
+
+  generateOutput () {
+    const assessment_result =  this.prepareResults();
+    let page = OutputAssessmentResult.PAGE_TEMPLATE;
+    page = page.replace(':assessment-result:', assessment_result);
+    page = page.replace(/(\r|\n|\t)/gm,'').replace(/> *</g, '><');
+    return page;
+  }
+
+  formatNumber (result) {
+    const result_class = result.grade == 1 ? 'assessment-number-result' : 'assessment-number-result-failed';
+    let template = this.formatOutput('assessment-number-expected',
+      'assessment-number-generated', result_class, result);
+    return template
+  }
+
+  formatBool (result) {
+    const result_class = result.grade == 1 ? 'assessment-bool-result' : 'assessment-bool-result-failed';
+    let template = this.formatOutput('assessment-bool-expected',
+      'assessment-bool-generated', result_class, result);
+    return template
+  }
+
+  formatOutput (expected_class, generated_class, result_class, result) {
+    let template = OutputAssessmentResult.OUTPUT_TEMPLATE;
+    template = template.replace(":class-expected:", expected_class);
+    template = template.replace(":class-generated:", generated_class);
+    template = template.replace(":class-result:", result_class);
+    let expected_tmpl = result.expected;
+    let generated_tmpl = result.generated;
+    if(expected_tmpl == null) {
+      expected_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0',
+        LocalizedStrings.getMessage('assessment-empty-expected-tooltip'));
+    } else if(generated_tmpl == null) {
+      generated_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0',
+        LocalizedStrings.getMessage('assessment-empty-generated-tooltip'));
+    }
+    template = template.replace("$0", expected_tmpl);
+    template = template.replace("$1", generated_tmpl);
+    const final_result = result.grade == 1 ? "✓" : "✗"
+    template = template.replace("$2", final_result);
+    return template
+  }
+
+  formatString (result) {
+    const expected_class = 'assessment-string-expected';
+    const generated_class = 'assessment-string-generated';
+    //const result_class = 'assessment-string-result';
+
+    let template = OutputAssessmentResult.OUTPUT_TEMPLATE;
+    template = template.replace(":class-expected:", expected_class);
+    template = template.replace(":class-generated:", generated_class);
+    //template = template.replace(":class-result:", result_class);
+
+    const g_string = result.generated || "";
+    const e_string = result.expected || "";
+    // console.log("generated: ", g_string,"expected: ", e_string);
+    let g_string_tmpl = g_string;
+    let e_string_tmpl = e_string;
+    if(result.generated == null) {
+      g_string_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0',
+        LocalizedStrings.getMessage('assessment-empty-generated-tooltip'));
+    } else if (result.expected == null) {
+     e_string_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0',
+        LocalizedStrings.getMessage('assessment-empty-expected-tooltip'));
+    }
+    template = template.replace("$0", e_string_tmpl);
+    template = template.replace("$1", g_string_tmpl);
+    if(result.grade == 1) {
+      template = template.replace("$2", "✓");
+      template = template.replace(":class-result:", 'assessment-string-result');
+    } else {
+      const diff = StringDiff(g_string, e_string);
+      // console.log(diff);
+      const diff_vec = diff.map(part => this.getDiffStringStyle(part[1], part[0]), this);
+      const diff_string = diff_vec.reduce((prev, actual) => prev + actual, "");
+      template = template.replace("$2", "<span class='assessment-failed-case'>✗</span>" + diff_string);
+      template = template.replace(":class-result:", "assessment-string-diff");
+    }
+    return template;
+  }
+
+  getDiffStringStyle (text, action) {
+    const template = "<span class='$0'>$1</span>"
+    // Fix missing whitespace when its a single element
+    text = text.replace(/\s/g,"&#160;");
+    switch(action) {
+      case StringDiff.INSERT:
+        return template.replace("$0", "stringdiff-insert").replace("$1", text);
+      case StringDiff.DELETE:
+        return template.replace("$0", "stringdiff-delete").replace("$1", text);
+      case StringDiff.EQUAL:
+        return template.replace("$0", "stringdiff-equal").replace("$1", text);
+    }
+  }
+}

+ 181 - 0
src/assessment/output_matching/output_matching.js

@@ -0,0 +1,181 @@
+import { Decimal } from 'decimal.js';
+import { InputAssessment } from "../../util/input_assessment";
+import { OutputTest } from "../../util/outputTest";
+import { Config } from "../../util/config";
+import { levenshteinDistance } from "../../util/utils";
+import { OutputAssessmentResult } from './assessment_result';
+import * as TypeParser from "./../../typeSystem/parsers";
+import * as LocalizedStringsService from "../../services/localizedStringsService";
+import * as OutputResult from "./output_result";
+
+const LocalizedStrings = LocalizedStringsService.getInstance();
+
+export class OutputMatching {
+
+  static get NUM_REGEX () {
+    return /^[+-]?([0-9]+([.][0-9]*)?(e[+-]?[0-9]+)?)$/;
+  }
+
+  static get NUM_IN_STRING_REGEX () {
+    return /[+-]?([0-9]+([.][0-9]*)?(e[+-]?[0-9]+)?)/g;
+  }
+
+  static get BOOLEAN_REGEX () {
+    const str = `^(${LocalizedStrings.getUI("logic_value_true")}|${LocalizedStrings.getUI("logic_value_false")})$`;
+    return new RegExp(str);
+  }
+
+  static get BOOLEAN_IN_STRING_REGEX () {
+    const str = `(${LocalizedStrings.getUI("logic_value_true")}|${LocalizedStrings.getUI("logic_value_false")})`;
+    return new RegExp(str, 'g');
+  }
+
+  constructor (program, input_list, expected_output, test_name) {
+    this.program = program;
+    this.name = test_name;
+    this.input_list = input_list;
+    this.expected_output = expected_output;
+  }
+
+  eval () {
+    const refThis = this;
+    const input = new InputAssessment(this.input_list);
+    const gen_output = new OutputTest();
+    this.program.registerInput(input);
+    this.program.registerOutput(gen_output);
+    const start_time = Date.now();
+    return this.program.interpretAST().then( sto => {
+      const final_time = Date.now() - start_time;
+      if(input.isInputAvailable()) {
+        return new OutputAssessmentResult(this.name, 1, input.input_list,
+          null, sto, final_time, refThis.getErrorMessage('test_case_few_reads', this.name+1))
+      }
+      const result = gen_output.list.map((g_out, i) => {
+        if(i >= this.expected_output.length) {
+          return new OutputResult.OutputMatchResult(null, g_out, 0, this.getPotentialOutputType(g_out));
+        }
+        return this.outputMatch(g_out, this.expected_output[i]);
+      }, this);
+      if(this.expected_output.length > gen_output.list.length) {
+        console.log("Saída insuficientes!",this.expected_output.length,gen_output.list.length);
+        for(let i = gen_output.list.length; i < this.expected_output.length; ++i) {
+          const e_out = this.expected_output[i];
+          result.push(new OutputResult.OutputMatchResult(e_out, null, 0, this.getPotentialOutputType(e_out)));
+        }
+      } else if (this.expected_output.length == 0 && this.expected_output.length == gen_output.list.length) {
+        // no output expected....
+        result.push(new OutputResult.OutputMatchResult("", "", 1, "string"));
+      }
+      return new OutputAssessmentResult(this.name, 0,  input.input_list, result, sto, final_time);
+    }).catch(error => {
+      return new OutputAssessmentResult(this.name, 1,  input.input_list, null, null,
+        null, refThis.getErrorMessage('test_case_exception', this.name + 1, error.message))
+    });
+  }
+
+  getPotentialOutputType (output) {
+    if(OutputMatching.NUM_REGEX.test(output)) {
+      return "number";
+    } else if (OutputMatching.BOOLEAN_REGEX.test(output)) {
+      return "bool";
+    } else {
+      return "string";
+    }
+  }
+
+  outputMatch (g_output, e_output) {
+    if(OutputMatching.NUM_REGEX.test(e_output)) {
+      if(!OutputMatching.NUM_REGEX.test(g_output)) {
+        return this.checkStrings(g_output, e_output);
+      }
+      const g_num = new Decimal(g_output);
+      const e_num = new Decimal(e_output);
+      return this.checkNumbers(g_num, e_num);
+    } else if (OutputMatching.BOOLEAN_REGEX.test(e_output)) {
+      if (!OutputMatching.BOOLEAN_REGEX.test(g_output)) {
+        return this.checkStrings(g_output, e_output)
+      }
+      const g_bool = TypeParser.toBool(g_output);
+      const e_bool = TypeParser.toBool(e_output);
+      return this.checkBoolean(g_bool, e_bool);
+    } else {
+      return this.checkStrings(g_output, e_output);
+    }
+  }
+
+  checkNumbers (g_num, e_num) {
+    const decimalPlaces = Math.min(e_num.dp(), Config.decimalPlaces);
+    g_num = new Decimal(g_num.toFixed(decimalPlaces, Decimal.ROUND_FLOOR));
+    e_num = new Decimal(e_num.toFixed(decimalPlaces, Decimal.ROUND_FLOOR));
+    const result = g_num.eq(e_num);
+    const grade = result ? 1 : 0;
+    return OutputResult.createNumberResult(e_num.toNumber(), g_num.toNumber(), grade);
+  }
+
+  checkBoolean (g_bool, e_bool) {
+    const grade = g_bool == e_bool ? 1 : 0;
+    const g_bool_text = TypeParser.convertBoolToString(g_bool);
+    const e_bool_text = TypeParser.convertBoolToString(e_bool);
+    return OutputResult.createBoolResult(e_bool_text, g_bool_text, grade);
+  }
+
+  checkStrings (g_output, e_ouput) {
+    const assessmentList = []
+    let e_output_clean = e_ouput.trim();
+    let g_output_clean = g_output.trim();
+    if (OutputMatching.NUM_IN_STRING_REGEX.test(e_ouput)) {
+      const expected_numbers = e_ouput.match(OutputMatching.NUM_IN_STRING_REGEX);
+      const generated_numbers = g_output.match(OutputMatching.NUM_IN_STRING_REGEX) || [];
+      const result = generated_numbers.map((val, i) => {
+        if(i >= expected_numbers.length) {
+          return OutputResult.createNumberResult(null, val, 0);
+        }
+        const g_val = new Decimal(val)
+        const e_val = new Decimal(expected_numbers[i]);
+        return this.checkNumbers(g_val, e_val);
+      }, this);
+      if(expected_numbers.length > generated_numbers.length) {
+        for(let i = generated_numbers.length; i < expected_numbers.length; ++i) {
+          result.push(OutputResult.createNumberResult(expected_numbers[i], null, 0));
+        }
+      }
+      e_output_clean = e_output_clean.replace(OutputMatching.NUM_IN_STRING_REGEX, '');
+      g_output_clean = g_output_clean.replace(OutputMatching.NUM_IN_STRING_REGEX, '');
+      const numberGrade = result.reduce((prev, r) => prev + r.grade, 0) / result.length;
+      assessmentList.push(numberGrade);
+    }
+    if(OutputMatching.BOOLEAN_IN_STRING_REGEX.test(e_ouput)) {
+      const expected_bools = e_ouput.match(OutputMatching.BOOLEAN_IN_STRING_REGEX);
+      const generated_bools = g_output.match(OutputMatching.BOOLEAN_IN_STRING_REGEX) || [];
+      const result = generated_bools.map((val, i) => {
+        if(i >= expected_bools.length) {
+          return OutputResult.createBoolResult(null, val, 0);
+        }
+        const g_bool = TypeParser.toBool(val);
+        const e_bool = TypeParser.toBool(expected_bools[i]);
+        return this.checkBoolean(g_bool, e_bool );
+      }, this);
+      if(expected_bools.length > generated_bools.length) {
+        for(let i = generated_bools.length; i < expected_bools.length; ++i) {
+          result.push(OutputResult.createBoolResult(expected_bools[i], null, 0));
+        }
+      }
+      e_output_clean = e_output_clean.replace(OutputMatching.BOOLEAN_IN_STRING_REGEX, '');
+      g_output_clean = g_output_clean.replace(OutputMatching.BOOLEAN_IN_STRING_REGEX, '');
+      const boolGrade = result.reduce((prev, r) => prev + r.grade, 0) / result.length;
+      assessmentList.push(boolGrade);
+    }
+    const dist = levenshteinDistance(g_output_clean, e_output_clean);
+    let gradeDiff = Math.max(0, e_output_clean.length - dist)/e_output_clean.length;
+    gradeDiff = Number.isNaN(gradeDiff) ? 0 : gradeDiff;
+    const assessment_size = assessmentList.length + 1;
+    const gradeAcc = assessmentList.reduce((prev, val) => prev + val/assessment_size, 0);
+    const finalGrade = 1 * (gradeDiff/assessment_size + gradeAcc);
+    return OutputResult.createStringResult(e_ouput, g_output, finalGrade);
+  }
+
+  getErrorMessage (errorID, ...args) {
+    return LocalizedStrings.getError(errorID, args);
+  }
+}
+

+ 22 - 0
src/assessment/output_matching/output_result.js

@@ -0,0 +1,22 @@
+
+export function createNumberResult (expected, generated, grade) {
+  return new OutputMatchResult(expected, generated, grade, "number");
+}
+
+export function createBoolResult (expected, generated, grade) {
+  return new OutputMatchResult(expected, generated, grade, "bool");
+}
+
+export function createStringResult (expected, generated, grade) {
+  return new OutputMatchResult(expected, generated, grade, "string");
+}
+
+export class OutputMatchResult {
+
+  constructor (expected, generated, grade, type) {
+    this.expected = expected;
+    this.generated = generated;
+    this.grade = grade;
+    this.type = type;
+  }
+}

+ 47 - 0
src/ast/ASA.txt

@@ -0,0 +1,47 @@
+/*
+  Raiz(ASA)
+    |
+    |
+  DeclaraçõesGlobais + Funções
+
+  DeclaracaoGlobal
+    |
+    |
+  const? TIPO ID (= EAnd)?
+
+  Função
+    |
+    |
+  Declaracao => TIPO ID (= EAnd)?
+  Attribuição => ID = EAnd
+  IF, WHILE, SWITCH, FuncCall, RETURN
+
+  EAnd
+    |
+    |
+  EOR ( 'and' EAnd)?
+
+  EOR   => ENot ('or' EAnd)?
+
+  ENot  => 'not'? ER
+
+  ER    => E ((>=, <=, ==, >, <) E)?
+
+  E     => factor ((+, -) E)?
+
+  factor=> term ((*, /, %) factor)?
+
+  term  => literal || arrayAccess || FuncCall || ID || '('EAnd')'
+
+  arrayAccess
+    |
+    |
+  ID'['E']'('['E']')*
+
+  FuncCall
+    |
+    |
+  ID'('p.a')'
+
+  p.a => E (, p.a)?
+**/

+ 11 - 0
src/ast/ast_helpers.js

@@ -0,0 +1,11 @@
+import { SyntaxErrorFactory } from "./error/syntaxErrorFactory";
+
+export function recover (_) {
+    const start = this._tokenStartCharIndex;
+    const stop = this._input.index;
+    let text = this._input.getText(start, stop);
+    text = this.getErrorDisplay(text);
+    const line = this._tokenStartLine;
+    const column = this._tokenStartColumn;
+    throw SyntaxErrorFactory.invalid_character(text, line, column);
+}

+ 10 - 0
src/ast/commands/arrayAssign.js

@@ -0,0 +1,10 @@
+import { Assign } from './assign';
+
+export class ArrayIndexAssign extends Assign {
+
+  constructor (id, lineExpression, columnExpression, expression) {
+    super(id, expression);
+    this.line = lineExpression;
+    this.column = columnExpression;
+  }
+}

+ 14 - 0
src/ast/commands/arrayDeclaration.js

@@ -0,0 +1,14 @@
+import { Declaration } from './declaration';
+
+export class ArrayDeclaration extends Declaration {
+
+  constructor (id, type, lines, columns, initial, isConst)   {
+    super(id, type, initial, isConst);
+    this.lines = lines;
+    this.columns = columns;
+  }
+
+  get isVector () {
+    return this.columns == null;
+  }
+}

+ 10 - 0
src/ast/commands/assign.js

@@ -0,0 +1,10 @@
+import { Command } from './command';
+
+export class Assign extends Command {
+  
+  constructor (id, expression) {
+    super();
+    this.id = id;
+    this.expression = expression;
+  }
+}

+ 8 - 0
src/ast/commands/break.js

@@ -0,0 +1,8 @@
+import { Command } from './command';
+
+export class Break extends Command {
+
+  constructor () {
+    super();
+  }
+}

+ 25 - 0
src/ast/commands/case.js

@@ -0,0 +1,25 @@
+import { Command } from './command';
+
+export class Case extends Command {
+
+  constructor (expression) {
+    super();
+    this.expression = expression;
+    /**
+     * @type {Command[]}
+     */
+    this.commands = [];
+  }
+
+  /**
+   * 
+   * @param {Command[]} commands 
+   */
+  setCommands (commands) {
+    this.commands = commands;
+  }
+
+  get isDefault () {
+    return this.expression === null;
+  }
+}

+ 14 - 0
src/ast/commands/command.js

@@ -0,0 +1,14 @@
+export class Command {
+
+  constructor () {
+    this._sourceInfo = null;
+  }
+
+  set sourceInfo (sourceInfo) {
+    this._sourceInfo = sourceInfo;
+  }
+
+  get sourceInfo () {
+    return this._sourceInfo;
+  }
+}

+ 16 - 0
src/ast/commands/commandBlock.js

@@ -0,0 +1,16 @@
+export class CommandBlock {
+	
+	constructor(variables, commands) {
+		this.variables = variables;
+		this.commands = commands;
+		this._sourceInfo = null;
+	}
+
+	set sourceInfo (sourceInfo) {
+		this._sourceInfo = sourceInfo;
+	}
+
+	get sourceInfo () {
+		return this._sourceInfo;
+	}
+}

+ 12 - 0
src/ast/commands/declaration.js

@@ -0,0 +1,12 @@
+import { Command } from './command';
+
+export class Declaration extends Command {
+  
+  constructor (id, type, initial, isConst) {
+    super();
+    this.id = id;
+    this.type = type;
+    this.initial = initial;
+    this.isConst = isConst;
+  }
+}

+ 17 - 0
src/ast/commands/for.js

@@ -0,0 +1,17 @@
+import { Command } from './command';
+
+export class For extends Command {
+
+  constructor (for_id, for_from, for_to, for_pass, commandBlock) {
+    super();
+    this.for_id = for_id;
+    this.for_from = for_from;
+    this.for_to = for_to;
+    this.for_pass = for_pass;
+    this.commandBlock = commandBlock;
+  }
+
+  get commands () {
+    return this.commandBlock.commands;
+  }
+}

+ 18 - 0
src/ast/commands/formalParameter.js

@@ -0,0 +1,18 @@
+export class FormalParameter {
+
+  constructor (type, id, byRef = false, variadic = false) {
+    this.type = type;
+    this.id = id;
+    this.byRef = byRef;
+    this.variadic = variadic;
+    this._sourceInfo = null;
+  }
+
+  set sourceInfo (sourceInfo) {
+		this._sourceInfo = sourceInfo;
+	}
+
+	get sourceInfo () {
+		return this._sourceInfo;
+	}
+}

+ 43 - 0
src/ast/commands/function.js

@@ -0,0 +1,43 @@
+import { Types } from './../../typeSystem/types';
+
+export class Function {
+
+  /**
+   * 
+   * @param {string} name 
+   * @param {import('./../../typeSystem/itype').IType} returnType 
+   * @param {import('./formalParameter').FormalParameter[]} formalParameters 
+   * @param {import('./commandBlock').CommandBlock} commandBlock 
+   */
+  constructor (name, returnType, formalParameters, commandBlock) {
+    this.name = name;
+    this.returnType = returnType;
+    this.formalParameters = formalParameters;
+    this.commandBlock = commandBlock;
+    this._sourceInfo = null;
+  }
+
+  get isMain () {
+    return this.name === null && this.returnType.isCompatible(Types.VOID);
+  }
+
+  get commands () {
+    return this.commandBlock.commands;
+  }
+
+  get variablesDeclarations () {
+    return this.commandBlock.variables;
+  }
+
+  set sourceInfo (sourceInfo) {
+		this._sourceInfo = sourceInfo;
+	}
+
+	get sourceInfo () {
+		return this._sourceInfo;
+  }
+  
+  hasVariadic () {
+    return this.formalParameters.some( p => p.variadic);
+  }
+}

+ 11 - 0
src/ast/commands/ifThenElse.js

@@ -0,0 +1,11 @@
+import { Command } from './command';
+
+export class IfThenElse extends Command {
+
+  constructor (condition, ifTrue, ifFalse) {
+    super();
+    this.condition = condition;
+    this.ifTrue = ifTrue;
+    this.ifFalse = ifFalse;
+  }
+}

+ 37 - 0
src/ast/commands/index.js

@@ -0,0 +1,37 @@
+import { Break } from './break';
+import { Return } from './return';
+import { Assign } from './assign';
+import { ArrayIndexAssign } from './arrayAssign';
+import { Declaration } from './declaration';
+import { ArrayDeclaration } from './arrayDeclaration';
+import { While } from './while';
+import { For } from './for';
+import { Function } from './function';
+import { IfThenElse } from './ifThenElse';
+import { CommandBlock } from './commandBlock';
+import { RepeatUntil } from './repeatUntil';
+import { Switch } from './switch';
+import { Case } from './case';
+import { SysCall } from './sysCall';
+import { FormalParameter } from './formalParameter';
+import { FunctionCall } from './../expressions/functionCall'; //Proxy to expression since they do exatcly the same thing
+
+export {
+  Break,
+  Return,
+  Assign,
+  ArrayIndexAssign,
+  Declaration,
+  ArrayDeclaration,
+  While,
+  For,
+  Function,
+  IfThenElse,
+  CommandBlock,
+  RepeatUntil,
+  Switch,
+  Case,
+  SysCall,
+  FormalParameter,
+  FunctionCall
+};

+ 13 - 0
src/ast/commands/repeatUntil.js

@@ -0,0 +1,13 @@
+import { While } from './while';
+
+export class RepeatUntil extends While {
+
+  constructor(condition, commandBlock) {
+    super(condition, commandBlock);
+  }
+
+  get testFirst () {
+    return false;
+  }
+  
+}

+ 10 - 0
src/ast/commands/return.js

@@ -0,0 +1,10 @@
+import { Command } from './command';
+
+export class Return extends Command {
+
+  constructor(expression) {
+    super();
+    this.expression = expression;
+  }
+  
+}

+ 19 - 0
src/ast/commands/switch.js

@@ -0,0 +1,19 @@
+import { Command } from './command';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Expression } from '../expressions/expression';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Case } from '.';
+
+export class Switch extends Command {
+  
+  /**
+   * 
+   * @param {Expression} expression 
+   * @param {Case[]} cases 
+   */
+  constructor (expression, cases) {
+    super();
+    this.expression = expression;
+    this.cases = cases;
+  }
+}

+ 12 - 0
src/ast/commands/sysCall.js

@@ -0,0 +1,12 @@
+/**
+ * This class represents all the language defined functions.
+ * The language processor uses the id provided here to properly execute the desired function.
+ * The function is actually implemented inside the language processor.
+ * All the functions can be found at: js/processor/definedFunctions.js
+ */
+export class SysCall {
+
+  constructor (langFunc) {
+    this.langFunc = langFunc;
+  }
+}

+ 18 - 0
src/ast/commands/while.js

@@ -0,0 +1,18 @@
+import { Command } from './command';
+
+export class While extends Command {
+
+  constructor (expression, commandBlock) {
+    super();
+    this.expression = expression;
+    this.commandBlock = commandBlock;
+  }
+
+  get commands () {
+    return this.commandBlock.commands;
+  }
+
+  get testFirst () {
+  	return true;
+  }
+}

+ 16 - 0
src/ast/error/syntaxError.js

@@ -0,0 +1,16 @@
+export class SyntaxError extends Error {
+  constructor (msg, id) {
+    super(msg);
+    this.id = id;
+    this._context = {};
+    if (Error.captureStackTrace) Error.captureStackTrace(this, SyntaxError);
+  }
+
+  get context () {
+    return this._context;
+  }
+
+  set context (contextObj) {
+    this._context = contextObj;
+  }
+}

+ 193 - 0
src/ast/error/syntaxErrorFactory.js

@@ -0,0 +1,193 @@
+import * as LocalizedStringsService from "./../../services/localizedStringsService";
+import { SyntaxError } from "./syntaxError";
+
+const LocalizedStrings = LocalizedStringsService.getInstance();
+
+function createError (message_id, context = []) {
+  return new SyntaxError(
+    LocalizedStrings.getError(message_id, context),
+    message_id
+  );
+}
+
+export const SyntaxErrorFactory = Object.freeze({
+  extra_lines: () => new SyntaxError(LocalizedStrings.getError("extra_lines")),
+  token_missing_one: (expected, token) => {
+    const context = [expected, token.text, token.line, token.col];
+    const error = createError("token_missing_one", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  token_missing_list: (expectedList, token) => {
+    const line = expectedList.join(LocalizedStrings.getOR());
+    const error = SyntaxErrorFactory.token_missing_one(line, token);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  id_missing: (token) => {
+    const context = [token.text, token.line, token.col];
+    const error = createError("id_missing", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  eos_missing: (token) => {
+    const context = [token.line, token.col];
+    const error = createError("eos_missing", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_array_dimension: (typeName, token) => {
+    const context = [token.line, token.col, typeName];
+    const error = createError("invalid_array_dimension", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_array_size: (token) => {
+    const context = [token.line];
+    const error = createError("invalid_array_size", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_main_return: (name, typeName, token) => {
+    const context = [name, typeName, token.line];
+    const error = createError("invalid_main_return", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_var_declaration: (token) => {
+    const context = [token.line];
+    const error = createError("invalid_var_declaration", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_break_command: (cmdName, token) => {
+    const context = [token.line, cmdName];
+    const error = createError("invalid_break_command", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_terminal: (token) => {
+    const context = [token.text, token.line, token.col];
+    const error = createError("invalid_terminal", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_type: (list, token) => {
+    const line = list.join(LocalizedStrings.getOR());
+    const context = [token.text, token.line, token.col, line];
+    const error = createError("invalid_type", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  const_not_init: (token) => {
+    const context = [token.line, token.col];
+    const error = createError("const_not_init", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_id_format: (token) => {
+    const context = [token.text, token.line, token.col];
+    const error = createError("invalid_id_format", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  duplicate_function: (token) => {
+    const context = [token.text, token.line, token.col];
+    const error = createError("duplicate_function", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  main_parameters: () => {
+    return createError("main_parameters");
+  },
+  duplicate_variable: (token) => {
+    const context = [token.text, token.line, token.col];
+    const error = createError("duplicate_variable", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_character: (text, line, column) => {
+    const context = [text, line];
+    const error = createError("invalid_character", context);
+    error.context = { line: line, column: column };
+    return error;
+  },
+  annonymous_array_literal: (token) => {
+    const context = [token.line];
+    const error = createError("annonymous_array_literal", context);
+    error.context = { line: token.line, column: token.col};
+    return error;
+  },
+  invalid_matrix_literal_line: (exp, sourceInfo) => {
+    const context = [exp, sourceInfo.line];
+    const error = createError("invalid_matrix_literal_line", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  cannot_infer_matrix_line: (name, sourceInfo) => {
+    const context = [name, sourceInfo.line];
+    const error = createError("cannot_infer_matrix_line", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  cannot_infer_matrix_column: (name, sourceInfo) => {
+    const context = [name, sourceInfo.line];
+    const error = createError("cannot_infer_matrix_column", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  cannot_infer_vector_size: (name, sourceInfo) => {
+    const context = [name, sourceInfo.line];
+    const error = createError("cannot_infer_vector_size", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  matrix_to_vector_literal_attr: (name, exp, sourceInfo) => {
+    const context = [sourceInfo.line, exp, name];
+    const error = createError("matrix_to_vector_literal_attr", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  vector_to_matrix_literal_attr: (name, exp, sourceInfo) => {
+    const context = [sourceInfo.line, exp, name];
+    const error = createError("vector_to_matrix_literal_attr", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  array_init_not_literal: (sourceInfo) => {
+    const context = [sourceInfo.line];
+    const error = createError("array_init_not_literal", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  array_exceeds_2d: (sourceInfo) => {
+    const context = [sourceInfo.line];
+    const error = createError("array_exceeds_2d", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  invalid_matrix_id_dimension: (sourceInfo) => {
+    const context = [sourceInfo.line];
+    const error = createError("invalid_matrix_id_dimension", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  invalid_vector_init: (sourceInfo) => {
+    const context = [sourceInfo.line];
+    const error = createError("invalid_vector_init", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  invalid_matrix_init: (sourceInfo) => {
+    const context = [sourceInfo.line];
+    const error = createError("invalid_matrix_init", context);
+    error.context = { line: sourceInfo.line, column: sourceInfo.column };
+    return error;
+  },
+  invalid_syntax: (text, line, column) => {
+    const context = [text, line];
+    const error = createError("invalid_syntax", context);
+    error.context = { line: line, column: column };
+    return error;
+  }
+});

+ 30 - 0
src/ast/expressions/arrayAccess.js

@@ -0,0 +1,30 @@
+import { Expression } from './expression';
+
+export class ArrayAccess extends Expression {
+	
+	constructor (id, line, column) {
+		super();
+		this.id = id;
+		this.line = line;
+		this.column = column;
+	}
+
+	toString () {
+		const strLine = this.line.toString();
+		let strColumn = null;
+		if(this.column) {
+			strColumn = this.column.toString();
+		}
+		let text = null;
+		if(strColumn) {
+			text = `${this.id}[${strLine}][${strColumn}]`;
+		} else {
+			text = `${this.id}[${strLine}]`;
+		}
+		if(this.parenthesis ){
+			return `(${text})`
+		} else {
+			return text;
+		}
+	}
+}

+ 101 - 0
src/ast/expressions/arrayLiteral.js

@@ -0,0 +1,101 @@
+import { Literal } from './literal';
+
+export class ArrayLiteral extends Literal {
+  
+  /**
+   * 
+   * @param {import('../../typeSystem/itype').IType} type 
+   * @param {import('./expression').Expression[]} value 
+   */
+  constructor(type, value) {
+    super(type);
+    this.value = value;
+  }
+
+  get subtype () {
+    const element = this.value[0];
+    if (element instanceof ArrayLiteral) {
+      return element.value[0].type;
+    } else {
+      return element.type;
+    }
+  }
+
+  get lines () {
+    return this.value.length;
+  }
+
+  get columns () {
+    const element = this.value[0];
+    if (!(element instanceof ArrayLiteral)){
+      return null;
+    } else {
+      return element.value.length;
+    }
+  }
+
+  get isVector () {
+    return this.columns === null;
+  }
+
+  get isValid () {
+    return this.validateSize() && this.validateType();
+  }
+
+  validateType () {
+    const valid = true;
+    // const subtype = this.subtype;
+    // if(this.columns !== null) {
+    //   const len = this.lines;
+    //   const len2 = this.columns;
+    //   for (let i = len - 1; i >= 0 && valid; --i) {
+    //     for (let j = len2 - 1; j >= 0 && valid; --j) {
+    //       if(!this.value[i].value[j].type.isCompatilbe(subtype)) {
+    //         valid = false;
+    //         break;
+    //       }
+    //     }
+    //   }
+    // } else {
+    //   const len = this.lines;
+    //   for (var i = len - 1; i >= 0 && valid; i--) {
+    //     if(!this.value[i].type.isCompatilbe(subtype)) {
+    //       valid = false;
+    //       break;
+    //     }
+    //   }
+    // }
+    // Cannot validate type since no information on variables literals are available
+    return valid;
+  }
+
+  validateSize () {
+    const valid = true;
+    // if(this.columns !== null) {
+    //   const equalityTest = this.value.map(v => v.value.length)
+    //     .reduce((old, next) => {
+    //       console.log(next);
+    //       if (old == null) {
+    //         return next;
+    //       } else if (old === next) {
+    //         return old
+    //       } else {
+    //         return -1;
+    //       }
+    //     }, null);
+    //   valid = equalityTest !== -1;
+    // }
+    // check is now made inside IVProgParser.parseVectorList(...)
+    return valid;
+  }
+
+  toString () {
+    const strList = this.value.map(arrayLiteral => arrayLiteral.toString());
+    const text = "{" + strList.join(',') + "}";
+    if(this.parenthesis) {
+      return `(${text})`;
+    } else {
+      return text;
+    }
+  }
+}

+ 20 - 0
src/ast/expressions/boolLiteral.js

@@ -0,0 +1,20 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+import { convertBoolToString } from "./../../typeSystem/parsers";
+
+export class BoolLiteral extends Literal {
+  
+  constructor (value) {
+    super(Types.BOOLEAN);
+    this.value = value;
+  }
+
+  toString () {
+    const text = convertBoolToString(this.value);
+    if(this.parenthesis) {
+      return `(${text})`
+    } else {
+      return text;
+    }
+  }
+}

+ 19 - 0
src/ast/expressions/charLiteral.js

@@ -0,0 +1,19 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+
+export class CharLiteral extends Literal {
+  
+  constructor (value) {
+    super(Types.CHAR);
+    this.value = value;
+  }
+
+  toString () {
+    const text = `'${this.value}'`;
+    if(this.parenthesis) {
+      return `(${text})`
+    } else {
+      return text;
+    }
+  }
+}

+ 23 - 0
src/ast/expressions/expression.js

@@ -0,0 +1,23 @@
+export class Expression {
+
+  constructor () {
+		this._sourceInfo = null;
+		this._parenthesis = false;
+  }
+
+  set sourceInfo (sourceInfo) {
+		this._sourceInfo = sourceInfo;
+	}
+
+	get sourceInfo () {
+		return this._sourceInfo;
+	}
+
+	set parenthesis (flag) {
+		this._parenthesis = flag;
+	}
+
+	get parenthesis () {
+		return this._parenthesis;
+	}
+}

+ 45 - 0
src/ast/expressions/functionCall.js

@@ -0,0 +1,45 @@
+import { Expression } from './expression';
+import { LanguageDefinedFunction } from '../../processor/definedFunctions';
+
+export class FunctionCall extends Expression {
+
+	/**
+	 * 
+	 * @param {string} id 
+	 * @param {Expression[]} actualParameters 
+	 */
+	constructor (id, actualParameters) {
+		super();
+		this.id = id;
+		this.actualParameters = actualParameters;
+	}
+
+	get isMainCall () {
+		return this.id === null;
+	}
+
+	get parametersSize () {
+		return this.actualParameters.length;
+	}
+
+	toString () {
+		let name = null;
+		if(this.isMainCall) {
+			name = LanguageDefinedFunction.getMainFunctionName();
+		} else {
+			name = LanguageDefinedFunction.getLocalName(this.id);
+		}
+		let params = null;
+		if(this.actualParameters.length == 0) {
+			params = "()";
+		} else {
+			const strParams = this.actualParameters.map(v => v.toString());
+			params = "(" + strParams.join(",") + ")";
+		}
+		if(this.parenthesis) {
+			return `(${name + params})`;
+		} else {
+			return name + params;
+		}
+	}
+}

+ 25 - 0
src/ast/expressions/index.js

@@ -0,0 +1,25 @@
+import { ArrayAccess } from './arrayAccess';
+import { FunctionCall } from './functionCall';
+import { IntLiteral } from './intLiteral';
+import { RealLiteral } from './realLiteral';
+import { BoolLiteral } from './boolLiteral';
+import { CharLiteral } from './charLiteral'
+import { StringLiteral } from './stringLiteral';
+import { ArrayLiteral } from './arrayLiteral';
+import { VariableLiteral } from './variableLiteral';
+import { InfixApp } from './infixApp';
+import { UnaryApp } from './unaryApp';
+
+export {
+	ArrayAccess,
+	FunctionCall,
+  IntLiteral,
+  RealLiteral,
+  BoolLiteral,
+  CharLiteral,
+  StringLiteral,
+  ArrayLiteral,
+  VariableLiteral,
+  InfixApp,
+  UnaryApp
+};

+ 22 - 0
src/ast/expressions/infixApp.js

@@ -0,0 +1,22 @@
+import { Expression } from './expression';
+
+export class InfixApp extends Expression {
+
+  constructor(op, left, right) {
+    super();
+    this.op = op;
+    this.left = left;
+    this.right = right;
+  }
+
+  toString () {
+    const l = this.left.toString();
+    const op = this.op.value;
+    const r = this.right.toString();
+    if(this.parenthesis) {
+      return  `(${l + op + r})`;
+    } else {
+      return l + op + r;
+    }
+  }
+}

+ 20 - 0
src/ast/expressions/intLiteral.js

@@ -0,0 +1,20 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+import { convertToString } from './../../typeSystem/parsers';
+
+export class IntLiteral extends Literal {
+  
+  constructor (value) {
+    super(Types.INTEGER);
+    this.value = value;
+  }
+
+  toString () {
+    const text = convertToString(this.value, this.type);
+    if(this.parenthesis) {
+      return `(${text})`;
+    } else {
+      return text;
+    }
+  }
+}

+ 9 - 0
src/ast/expressions/literal.js

@@ -0,0 +1,9 @@
+import { Expression } from './expression';
+
+export class Literal extends Expression {
+  
+  constructor (type) {
+    super();
+    this.type = type;
+  }
+}

+ 20 - 0
src/ast/expressions/realLiteral.js

@@ -0,0 +1,20 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+import { convertToString } from './../../typeSystem/parsers';
+
+export class RealLiteral extends Literal {
+  
+  constructor (value) {
+    super(Types.REAL);
+    this.value = value;
+  }
+
+  toString () {
+    const text = convertToString(this.value, this.type);
+    if (this.parenthesis) {
+      return `(${text})`;
+    } else {
+      return text;
+    }
+  }
+}

+ 19 - 0
src/ast/expressions/stringLiteral.js

@@ -0,0 +1,19 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+
+export class StringLiteral extends Literal {
+  
+  constructor (value) {
+    super(Types.STRING);
+    this.value = value;
+  }
+
+  toString () {
+    const text = '"' + this.value + '"';
+    if(this.parenthesis) {
+      return `(${text})`;
+    } else {
+      return text;
+    }
+  }
+}

+ 18 - 0
src/ast/expressions/unaryApp.js

@@ -0,0 +1,18 @@
+import {InfixApp} from './infixApp';
+
+export class UnaryApp extends InfixApp {
+  
+  constructor (op, left) {
+    super(op, left, null);
+  }
+
+  toString () {
+    const l = this.left.toString();
+    const op = this.op.value;
+    if(this.parenthesis) {
+      return `(${op + l})`;
+    } else {
+      return op + l;
+    }
+  }
+}

+ 18 - 0
src/ast/expressions/variableLiteral.js

@@ -0,0 +1,18 @@
+import { Literal } from './literal';
+import { Types } from './../../typeSystem/types';
+
+export class VariableLiteral extends Literal {
+  
+  constructor (id) {
+    super(Types.UNDEFINED);
+    this.id = id;
+  }
+
+  toString () {
+    if(this.parenthesis) {
+      return `(${this.id})`;
+    } else {
+      return this.id;
+    }
+  }
+}

File diff ditekan karena terlalu besar
+ 1572 - 0
src/ast/ivprogParser.js


+ 0 - 0
src/ast/operators.ts


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini