xxeell

TFLAT-4-interpretator

Nov 17th, 2021 (edited)
643
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5.     <title>Interpreter</title>
  6. </head>
  7.  
  8. <body>
  9.     <textarea id="input" cols="60" rows="10"></textarea>
  10.     <button id="parseButton">parse</button>
  11.     <br>
  12.     <details>
  13.         <summary>Лексемы</summary>
  14.         <div id="lexOutputContainer"></div>
  15.     </details>
  16.     <br>
  17.     <details>
  18.         <summary>Синтаксическое дерево</summary>
  19.         <div id="sintOutputContainer"></div>
  20.         <br>
  21.         <br>
  22.         <div id="sintOutputCanvas" width="100%" height="1000px"
  23.             style="vertical-align:top;text-anchor:middle;font-family:monospace;font-size:16px;"></div>
  24.     </details>
  25.     <br>
  26.     <details>
  27.         <summary>Полиз</summary>
  28.         <div id="polizOutputContainer"></div>
  29.     </details>
  30.     <br>
  31.     <details open>
  32.         <summary>Выполнение</summary>
  33.         <textarea id="interpretationOutputContainer" cols="60" rows="10" readonly></textarea>
  34.         <button id="interpretationButton">execute</button>
  35.         <div id="interpretationPathContainer"></div>
  36.         <br>
  37.     </details>
  38.  
  39. </body>
  40. <!-- IO -->
  41. <script>
  42.     const IOContainers = {
  43.         input: document.getElementById('input'),
  44.         lexOutput: document.getElementById('lexOutputContainer'),
  45.         sintOutput: document.getElementById('sintOutputContainer'),
  46.         polizOutput: document.getElementById('polizOutputContainer'),
  47.         interpretationOutput: document.getElementById('interpretationOutputContainer'),
  48.         interpretationPath: document.getElementById('interpretationPathContainer'),
  49.     };
  50.     IOContainers.input.value =
  51.         `read(a)
  52. b = 5
  53. c = 0
  54. do while (a < b)
  55.     write(c)
  56.     c = c + a
  57.     a = a + 1
  58. loop
  59. write(c)`;
  60. </script>
  61. <!-- Automate engine -->
  62. <script>
  63.     function distinct(array) {
  64.         return array.filter((value, index) => array.indexOf(value) == index);
  65.     }
  66.  
  67.     (function () {
  68.         let automateExample = {
  69.             states: {
  70.                 list: ['a', 'b', 'c'],
  71.                 start: 'a',
  72.                 end: ['c']
  73.             },
  74.             alphabet: [1, 2, 3],
  75.             translations: [
  76.                 { from: 'a', to: 'b', when: 1 },
  77.                 { from: 'b', to: 'c', when: 2 },
  78.                 { from: 'b', to: 'a', when: 2 },
  79.                 { from: 'a', to: 'c', when: 3 },
  80.             ],
  81.             epsilon: {
  82.                 useEpsilon: true,
  83.                 translations: [
  84.                     { from: 'b', to: 'a' },
  85.                     { from: 'b', to: 'b' },
  86.                 ],
  87.             },
  88.             config: {
  89.                 drowWhenNoTranslation: false,
  90.                 logEpsilonSeparately: true
  91.             }
  92.         };
  93.     })();
  94.  
  95.     function validateAutomateTemplate(automateTemplate) {
  96.         if (!automateTemplate) {
  97.             throw new Error(`Template error! Input is undefined.`);
  98.         }
  99.  
  100.         // --- --- States --- ---
  101.         if (!automateTemplate.states) {
  102.             throw new Error(`States error! States object is empty.`);
  103.         }
  104.         // --- list ---
  105.         if (!automateTemplate.states.list) {
  106.             throw new Error(`States error! States list is undefined.`);
  107.         }
  108.  
  109.         if (automateTemplate.states.list.length < 1) {
  110.             throw new Error(`States error! States list is empty.`);
  111.         }
  112.         // --- end list ---
  113.         // --- start ---
  114.         if (!automateTemplate.states.start) {
  115.             throw new Error(`Start state error! Start state is undefined.`);
  116.         }
  117.  
  118.         if (!automateTemplate.states.list.includes(automateTemplate.states.start)) {
  119.             throw new Error(`Start state error! States not include '${automateTemplate.states.start}'.`);
  120.         }
  121.         // --- end start ---
  122.         // --- end ---
  123.         if (!automateTemplate.states.end) {
  124.             throw new Error(`End states error! End states is undefined.`);
  125.         }
  126.  
  127.         if (automateTemplate.states.end.length < 1) {
  128.             throw new Error(`End states error! End states list is empty.`);
  129.         }
  130.  
  131.         for (const state of automateTemplate.states.end) {
  132.             if (!automateTemplate.states.list.includes(state)) {
  133.                 throw new Error(`End states error! States not include '${state}'.`);
  134.             }
  135.         }
  136.         // --- end end ---
  137.         // --- --- end States --- ---
  138.  
  139.         // --- --- Alphabet --- ---
  140.         if (!automateTemplate.alphabet) {
  141.             throw new Error(`Alphabet error! Alphabet is undefined.`);
  142.         }
  143.  
  144.         if (automateTemplate.alphabet.length < 1) {
  145.             throw new Error(`Alphabet error! Alphabet list is empty.`);
  146.         }
  147.         // --- --- end Alphabet --- ---
  148.  
  149.         // --- --- Translation --- ---
  150.         if (!automateTemplate.translations) {
  151.             throw new Error(`Translation error! Translations is undefined.`);
  152.         }
  153.  
  154.         if (automateTemplate.translations.length < 1) {
  155.             throw new Error(`Translation error! Translations list is empty.`);
  156.         }
  157.  
  158.         for (const translation of automateTemplate.translations) {
  159.             if (!automateTemplate.states.list.includes(translation.from)) {
  160.                 throw new Error(`Translation error! States not include 'from' value '${translation.from}' on transtalion ${JSON.stringify(translation)}.`);
  161.             }
  162.             if (!automateTemplate.states.list.includes(translation.to)) {
  163.                 throw new Error(`Translation error! States not include 'to' value '${translation.to}' on transtalion ${JSON.stringify(translation)}.`);
  164.             }
  165.             if (!automateTemplate.alphabet.includes(translation.when)) {
  166.                 throw new Error(`Translation error! Alphabet not include 'when' value '${translation.when}' on transtalion ${JSON.stringify(translation)}.`);
  167.             }
  168.         }
  169.         // --- --- end Translation --- ---
  170.  
  171.         // --- --- Epsilon --- ---
  172.         if (!automateTemplate.epsilon) {
  173.             throw new Error(`Epsilon error! Epsilon is undefined.`);
  174.         }
  175.  
  176.         if (automateTemplate.epsilon.useEpsilon) {
  177.             if (!automateTemplate.epsilon.translations) {
  178.                 throw new Error(`Epsilon error! Epsilon translations is undefined.`);
  179.             }
  180.  
  181.             if (automateTemplate.epsilon.translations.length < 1) {
  182.                 throw new Error(`Epsilon error! Epsilon translations list is empty.`);
  183.             }
  184.  
  185.             for (const translation of automateTemplate.epsilon.translations) {
  186.                 if (!automateTemplate.states.list.includes(translation.from)) {
  187.                     throw new Error(`Epsilon error! States not include 'from' value '${translation.from}' on epsilon transtalion ${JSON.stringify(translation)}.`);
  188.                 }
  189.                 if (!automateTemplate.states.list.includes(translation.to)) {
  190.                     throw new Error(`Epsilon error! States not include 'to' value '${translation.to}' on epsilon transtalion ${JSON.stringify(translation)}.`);
  191.                 }
  192.             }
  193.         }
  194.         // --- --- end Epsilon --- ---
  195.  
  196.         // --- --- Config --- ---
  197.         if (!automateTemplate.config) {
  198.             throw new Error(`Config error! Config is undefined.`);
  199.         }
  200.         // --- --- end Config --- ---
  201.     }
  202.  
  203.     function Automate(automateTemplate) {
  204.         validateAutomateTemplate(automateTemplate);
  205.  
  206.         this.automate = {
  207.             states: {
  208.                 list: Array.from(automateTemplate.states.list),
  209.                 start: automateTemplate.states.start,
  210.                 end: Array.from(automateTemplate.states.end)
  211.             },
  212.             alphabet: Array.from(automateTemplate.alphabet),
  213.             translations: {},
  214.             epsilon: {
  215.                 useEpsilon: false,
  216.                 translations: {}
  217.             },
  218.             config: {
  219.                 drowWhenNoTranslation: automateTemplate.config.drowWhenNoTranslation,
  220.                 logEpsilonSeparately: automateTemplate.config.logEpsilonSeparately
  221.             }
  222.         };
  223.  
  224.         for (const state of this.automate.states.list) {
  225.             this.automate.translations[state] = {};
  226.             for (const letter of this.automate.alphabet) {
  227.                 this.automate.translations[state][letter] = [];
  228.             }
  229.         }
  230.         for (const translation of automateTemplate.translations) {
  231.             if (this.automate.translations[translation.from][translation.when].includes(translation.to)) {
  232.                 throw new Error(`Translation error! Transtalion ${JSON.stringify(translation)} already exists.`);
  233.             }
  234.             this.automate.translations[translation.from][translation.when].push(translation.to);
  235.         }
  236.  
  237.         if (automateTemplate.epsilon.useEpsilon) {
  238.             this.automate.epsilon.useEpsilon = true;
  239.             for (const state of this.automate.states.list) {
  240.                 this.automate.epsilon.translations[state] = [];
  241.             }
  242.             for (const translation of automateTemplate.epsilon.translations) {
  243.                 if (this.automate.epsilon.translations[translation.from].includes(translation.to)) {
  244.                     throw new Error(`Epsilon translation error! Epsilon transtalion ${JSON.stringify(translation)} already exists.`);
  245.                 }
  246.                 this.automate.epsilon.translations[translation.from].push(translation.to);
  247.             }
  248.         }
  249.  
  250.         this.execution = {
  251.             current: [this.automate.states.start],
  252.             log: [],
  253.             errors: []
  254.         };
  255.     }
  256.  
  257.     Automate.prototype = {
  258.         clearExecution() {
  259.             this.execution = {
  260.                 current: [this.automate.states.start],
  261.                 log: [],
  262.                 errors: []
  263.             };
  264.             this.logStep(null);
  265.         },
  266.         logStep(letter) {
  267.             this.execution.log.push({
  268.                 getLetter: letter,
  269.                 resultStates: Array.from(this.execution.current)
  270.             });
  271.         },
  272.         processEpsilon() {
  273.             if (!this.automate.epsilon.useEpsilon) {
  274.                 return;
  275.             }
  276.  
  277.             let next = [...this.execution.current];
  278.             let currentChars = this.execution.current;
  279.             let nextChars = [];
  280.  
  281.             while (currentChars.length > 0) {
  282.                 for (let curChar of currentChars) {
  283.                     nextChars.push(...this.automate.epsilon.translations[curChar]);
  284.                 }
  285.                 next.push(...nextChars);
  286.                 currentChars = distinct(nextChars).filter(value => !next.includes(value));
  287.                 nextChars = [];
  288.             }
  289.  
  290.             this.execution.current = distinct(next);
  291.             if (this.automate.config.logEpsilonSeparately) {
  292.                 this.logStep('epsilon');
  293.             }
  294.         },
  295.         processLetter(letter) {
  296.             if (!this.automate.alphabet.includes(letter)) {
  297.                 alert(`Input error! Alphabet not include ${letter}`);
  298.                 return;
  299.             }
  300.  
  301.             let next = [];
  302.  
  303.             for (let currentState of this.execution.current) {
  304.                 let nextStates = this.automate.translations[currentState][letter];
  305.                 if (nextStates.length < 1) {
  306.                     let error = `No translation for ${JSON.stringify({ from: currentState, when: letter })}`;
  307.                     this.execution.errors.push(error);
  308.                     if (this.automate.config.drowWhenNoTranslation) {
  309.                         throw error;
  310.                     } else {
  311.                         nextStates = [currentState];
  312.                     }
  313.                 }
  314.                 next.push(...nextStates);
  315.             }
  316.  
  317.             this.execution.current = distinct(next);
  318.  
  319.             if (this.automate.config.logEpsilonSeparately) {
  320.                 this.logStep(letter);
  321.                 this.processEpsilon();
  322.             } else {
  323.                 this.processEpsilon();
  324.                 this.logStep(letter);
  325.             }
  326.         },
  327.         isComplete() {
  328.             return this.execution.current.some(value => this.automate.states.end.includes(value));
  329.         }
  330.     };
  331. </script>
  332. <!-- Lex classes -->
  333. <script>
  334.     const LexClasses = {
  335.         keywords: {
  336.             loop: {
  337.                 while: {
  338.                     start: { value: 'lex.keyword.loop.while.start', priority: 1 },
  339.                     end: { value: 'lex.keyword.loop.while.end', priority: 1 },
  340.                 }
  341.             },
  342.             codeSegment: {
  343.                 start: { value: 'lex.keyword.codeSegment.start', priority: 2 },
  344.                 end: { value: 'lex.keyword.codeSegment.end', priority: 2 },
  345.             },
  346.             IO: {
  347.                 read: { value: 'lex.keyword.IO.read', priority: 2 },
  348.                 write: { value: 'lex.keyword.IO.write', priority: 2 },
  349.             }
  350.         },
  351.         separators: {
  352.             bracket: {
  353.                 start: { value: 'lex.separators.bracket.start', priority: 3 },
  354.                 end: { value: 'lex.separators.bracket.end', priority: 3 },
  355.             }
  356.         },
  357.         operations: {
  358.             as: { value: 'lex.operations.as', priority: 3 },
  359.             logical: { value: 'lex.operations.logical', priority: 4 },
  360.             compare: { value: 'lex.operations.compare', priority: 4 },
  361.             math: { value: 'lex.operations.math', priority: 4 },
  362.         },
  363.         values: {
  364.             variable: { value: 'lex.values.variable', priority: 5 },
  365.             numConst: { value: 'lex.values.numConst', priority: 5 },
  366.         },
  367.     };
  368. </script>
  369. <!-- Automate builder -->
  370. <script>
  371.     const AutomateBuilder = {
  372.         alphabet: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>=+-*/ ()'.split(''),
  373.         createAutomateTemplate(keyword) {
  374.             let template = {
  375.                 states: {
  376.                     list: ['start'],
  377.                     start: 'start',
  378.                     end: [keyword]
  379.                 },
  380.                 alphabet: AutomateBuilder.alphabet,
  381.                 translations: [],
  382.                 epsilon: {
  383.                     useEpsilon: false,
  384.                     translations: [],
  385.                 },
  386.                 config: {
  387.                     drowWhenNoTranslation: true,
  388.                     logEpsilonSeparately: false
  389.                 }
  390.             };
  391.  
  392.             let wordPart = '';
  393.             for (const letter of keyword) {
  394.                 wordPart += letter;
  395.                 const prewState = template.states.list[template.states.list.length - 1];
  396.                 const curState = wordPart;
  397.                 template.states.list.push(curState);
  398.                 template.translations.push({ from: prewState, to: curState, when: letter });
  399.             }
  400.  
  401.             return template;
  402.         },
  403.         createAutomate(keyword) {
  404.             let template = AutomateBuilder.createAutomateTemplate(keyword);
  405.             let automate = new Automate(template);
  406.             return automate;
  407.         },
  408.         createNumConstAtomate() {
  409.             let template = {
  410.                 states: {
  411.                     list: ['start', 'num'],
  412.                     start: 'start',
  413.                     end: ['num']
  414.                 },
  415.                 alphabet: AutomateBuilder.alphabet,
  416.                 translations: [],
  417.                 epsilon: {
  418.                     useEpsilon: false,
  419.                     translations: [],
  420.                 },
  421.                 config: {
  422.                     drowWhenNoTranslation: true,
  423.                     logEpsilonSeparately: false
  424.                 }
  425.             };
  426.  
  427.             for (let letter of '0123456789') {
  428.                 template.translations.push({ from: 'start', to: 'num', when: letter });
  429.                 template.translations.push({ from: 'num', to: 'num', when: letter });
  430.             }
  431.  
  432.             let automate = new Automate(template);
  433.             return automate;
  434.         },
  435.         createVariableAtomate() {
  436.             let template = {
  437.                 states: {
  438.                     list: ['start', 'var'],
  439.                     start: 'start',
  440.                     end: ['var']
  441.                 },
  442.                 alphabet: AutomateBuilder.alphabet,
  443.                 translations: [],
  444.                 epsilon: {
  445.                     useEpsilon: false,
  446.                     translations: [],
  447.                 },
  448.                 config: {
  449.                     drowWhenNoTranslation: true,
  450.                     logEpsilonSeparately: false
  451.                 }
  452.             };
  453.  
  454.             for (let letter of 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
  455.                 template.translations.push({ from: 'start', to: 'var', when: letter });
  456.                 template.translations.push({ from: 'var', to: 'var', when: letter });
  457.             }
  458.  
  459.             for (let letter of '0123456789') {
  460.                 template.translations.push({ from: 'var', to: 'var', when: letter });
  461.             }
  462.  
  463.             let automate = new Automate(template);
  464.             return automate;
  465.         }
  466.     }
  467. </script>
  468. <!-- Automates -->
  469. <script>
  470.     const FullAutomatesList = {
  471.         // keywords,
  472.         while: {
  473.             automate: AutomateBuilder.createAutomate('while'),
  474.             class: LexClasses.keywords.loop.while.start
  475.         },
  476.         loop: {
  477.             automate: AutomateBuilder.createAutomate('loop'),
  478.             class: LexClasses.keywords.loop.while.end
  479.         },
  480.         do: {
  481.             automate: AutomateBuilder.createAutomate('do'),
  482.             class: LexClasses.keywords.codeSegment.start
  483.         },
  484.         end: {
  485.             automate: AutomateBuilder.createAutomate('end'),
  486.             class: LexClasses.keywords.codeSegment.end
  487.         },
  488.         read: {
  489.             automate: AutomateBuilder.createAutomate('read'),
  490.             class: LexClasses.keywords.IO.read
  491.         },
  492.         write: {
  493.             automate: AutomateBuilder.createAutomate('write'),
  494.             class: LexClasses.keywords.IO.write
  495.         },
  496.         // end keywords
  497.         // separators
  498.         '(': {
  499.             automate: AutomateBuilder.createAutomate('('),
  500.             class: LexClasses.separators.bracket.start
  501.         },
  502.         ')': {
  503.             automate: AutomateBuilder.createAutomate(')'),
  504.             class: LexClasses.separators.bracket.end
  505.         },
  506.         // end separators
  507.         // operations
  508.         and: {
  509.             automate: AutomateBuilder.createAutomate('and'),
  510.             class: LexClasses.operations.logical
  511.         },
  512.         or: {
  513.             automate: AutomateBuilder.createAutomate('or'),
  514.             class: LexClasses.operations.logical
  515.         },
  516.         '<': {
  517.             automate: AutomateBuilder.createAutomate('<'),
  518.             class: LexClasses.operations.compare
  519.         },
  520.         '>': {
  521.             automate: AutomateBuilder.createAutomate('>'),
  522.             class: LexClasses.operations.compare
  523.         },
  524.         '<=': {
  525.             automate: AutomateBuilder.createAutomate('<='),
  526.             class: LexClasses.operations.compare
  527.         },
  528.         '==': {
  529.             automate: AutomateBuilder.createAutomate('=='),
  530.             class: LexClasses.operations.compare
  531.         },
  532.         '<>': {
  533.             automate: AutomateBuilder.createAutomate('<>'),
  534.             class: LexClasses.operations.compare
  535.         },
  536.         '+': {
  537.             automate: AutomateBuilder.createAutomate('+'),
  538.             class: LexClasses.operations.math
  539.         },
  540.         '-': {
  541.             automate: AutomateBuilder.createAutomate('-'),
  542.             class: LexClasses.operations.math
  543.         },
  544.         '*': {
  545.             automate: AutomateBuilder.createAutomate('*'),
  546.             class: LexClasses.operations.math
  547.         },
  548.         '/': {
  549.             automate: AutomateBuilder.createAutomate('/'),
  550.             class: LexClasses.operations.math
  551.         },
  552.         '=': {
  553.             automate: AutomateBuilder.createAutomate('='),
  554.             class: LexClasses.operations.as
  555.         },
  556.         // end operations
  557.         // values
  558.         variable: {
  559.             automate: AutomateBuilder.createVariableAtomate(),
  560.             class: LexClasses.values.variable
  561.         },
  562.         numConst: {
  563.             automate: AutomateBuilder.createNumConstAtomate(),
  564.             class: LexClasses.values.numConst
  565.         },
  566.         // end values
  567.     }
  568. </script>
  569. <!-- Render -->
  570. <script>
  571.     const HTMLTags = {
  572.         Table: 'table',
  573.         TableRow: 'tr',
  574.         TableData: 'td'
  575.     }
  576.  
  577.     const ItemTypes = {
  578.         Value: 'VALUE',
  579.         Container: 'CONTAINER'
  580.     }
  581.  
  582.     function render(item) {
  583.         if (item.element) {
  584.             return item.element;
  585.         }
  586.  
  587.         let element = document.createElement(item.tag);
  588.         item.element = element;
  589.  
  590.         if (item.attributes) {
  591.             for (let name in item.attributes) {
  592.                 let value = item.attributes[name];
  593.                 element.setAttribute(name, value);
  594.             }
  595.         }
  596.  
  597.         switch (item.type) {
  598.             case ItemTypes.Value:
  599.                 if (item.value) {
  600.                     element.innerHTML = item.value;
  601.                 }
  602.                 break;
  603.             case ItemTypes.Container:
  604.                 if (item.childs) {
  605.                     for (let i in item.childs) {
  606.                         let child = item.childs[i];
  607.                         if (!child.element) {
  608.                             render(child);
  609.                         }
  610.                         element.append(child.element);
  611.                     }
  612.                 }
  613.                 break;
  614.         }
  615.  
  616.         return element;
  617.     }
  618. </script>
  619. <!-- Lex analizer -->
  620. <script>
  621.     function LexAnalizer(automatesList) {
  622.         this.automates = automatesList;
  623.         this.output = [];
  624.         this.execution = {
  625.             prevAutomates: [],
  626.             prevCompleteAutomates: [],
  627.             curAutomates: [],
  628.             accumulator: '',
  629.         };
  630.     }
  631.  
  632.     LexAnalizer.prototype = {
  633.         getAllAutomates() {
  634.             let list = Object.values(this.automates);
  635.             list.sort((a, b) => a.class.priority - b.class.priority);
  636.             list.forEach(element => element.automate.clearExecution());
  637.             return list;
  638.         },
  639.         getCompleteAutomates(automates) {
  640.             return automates.filter(value => value.automate.isComplete());
  641.         },
  642.         resetExecution() {
  643.             this.execution = {
  644.                 prevAutomates: this.getAllAutomates(),
  645.                 prevCompleteAutomates: null,
  646.                 curAutomates: [],
  647.                 accumulator: '',
  648.             };
  649.             this.execution.prevCompleteAutomates = this.getCompleteAutomates(this.execution.prevAutomates);
  650.         },
  651.         tryAddToOutput(index) {
  652.             if (this.execution.curAutomates.length < 1) {
  653.                 if (this.execution.prevAutomates.length > 0) {
  654.                     const lastAutomate = this.execution.prevCompleteAutomates[0];
  655.                     if (lastAutomate) {
  656.                         this.output.push({
  657.                             word: this.execution.accumulator,
  658.                             position: {
  659.                                 start: index - this.execution.accumulator.length,
  660.                                 end: index - 1
  661.                             },
  662.                             class: lastAutomate.class.value
  663.                         });
  664.                         return 3;
  665.                     }
  666.                     return 2;
  667.                 }
  668.                 return 1;
  669.             }
  670.             return 0;
  671.         },
  672.         prepareNextStep(letter) {
  673.             this.execution.prevAutomates = this.execution.curAutomates;
  674.             this.execution.prevCompleteAutomates = this.getCompleteAutomates(this.execution.prevAutomates);
  675.             this.execution.curAutomates = [];
  676.             this.execution.accumulator += letter;
  677.         },
  678.         analize(input) {
  679.             const space = ' ';
  680.             this.output = [];
  681.             this.resetExecution();
  682.             input = input.replaceAll(/\s+/g, space);
  683.  
  684.             for (let i = 0; i < input.length; i++) {
  685.                 const letter = input[i];
  686.  
  687.                 for (const automate of this.execution.prevAutomates) {
  688.                     try {
  689.                         automate.automate.processLetter(letter);
  690.                         this.execution.curAutomates.push(automate);
  691.                     } catch {
  692.                         automate.automate.clearExecution();
  693.                     }
  694.                 }
  695.  
  696.                 let stepFinished = this.tryAddToOutput(i);
  697.                 if (stepFinished) {
  698.                     this.resetExecution();
  699.                     if (letter != space) {
  700.                         i--;
  701.                     }
  702.                 } else {
  703.                     this.prepareNextStep(letter);
  704.                 }
  705.             }
  706.  
  707.             this.tryAddToOutput(input.length);
  708.         }
  709.     };
  710. </script>
  711. <!-- Sint classes -->
  712. <script>
  713.     const SintClasses = {
  714.         Value: 'sint.value',
  715.         // lex.values.variable
  716.         //  | lex.values.numConst
  717.         //  | lex.separators.bracket.start sint.math lex.separators.bracket.end
  718.         MathOperation: 'sint.math',
  719.         // sint.value lex.operations.math sint.math
  720.         //  | sint.value
  721.         LogicOperation: 'sint.logic.operation',
  722.         // lex.separators.bracket.start sint.math lex.operations.compare sint.math lex.separators.bracket.end
  723.         LogicExpression: 'sint.logic.expression',
  724.         // lex.separators.bracket.start sint.logic.expression lex.operations.logical sint.logic.expression lex.separators.bracket.end
  725.         //  | sint.logic.operation
  726.         Assignment: 'sint.assignment',
  727.         // lex.values.variable lex.operations.as sint.math
  728.         WhileLoop: 'sint.loop.while',
  729.         // lex.keyword.codeSegment.start lex.keyword.loop.while.start sint.logic.expression [sint.operation] lex.keyword.loop.while.end
  730.         Read: 'sint.read',
  731.         // lex.keyword.IO.read lex.separators.bracket.start lex.values.variable lex.separators.bracket.end
  732.         Write: 'sint.write',
  733.         // lex.keyword.IO.write lex.separators.bracket.start sint.math lex.separators.bracket.end
  734.         Operation: 'sint.operation',
  735.         // sint.assignment
  736.         //  | sint.loop.while
  737.         //  | sint.read
  738.         //  | sint.write
  739.         Code: 'sint.code',
  740.         // [sint.operation]
  741.     };
  742. </script>
  743. <!-- Poliz -->
  744. <script>
  745.     const PolizRecordType = {
  746.         Command: 'prCommand',
  747.         Variable: 'prVariable',
  748.         Const: 'prConst',
  749.         Pointer: 'prPointer',
  750.     };
  751.  
  752.     const PolizCommand = {
  753.         JMP: { value: 'JMP', index: 0 },
  754.         JZ: { value: 'JZ', index: 1 },
  755.         SET: { value: 'SET', index: 2 },
  756.         ADD: { value: 'ADD', index: 3 },
  757.         SUB: { value: 'SUB', index: 4 },
  758.         MUL: { value: 'MUL', index: 5 },
  759.         DIV: { value: 'DIV', index: 6 },
  760.         AND: { value: 'AND', index: 7 },
  761.         OR: { value: 'OR', index: 8 },
  762.         CMPE: { value: 'CMPE', index: 9 },
  763.         CMPNE: { value: 'CMPNE', index: 10 },
  764.         CMPL: { value: 'CMPL', index: 11 },
  765.         CMPLE: { value: 'CMPLE', index: 12 },
  766.         CMPG: { value: 'CMPG', index: 13 },
  767.         CMPGE: { value: 'CMPGE', index: 14 },
  768.         READ: { value: 'READ', index: 15 },
  769.         WRITE: { value: 'WRITE', index: 16 },
  770.     };
  771.  
  772.     const PolizCommandsList = (function () {
  773.         let commands = Object.values(PolizCommand);
  774.         commands.sort((a, b) => a.index - b.index);
  775.         return commands.map(value => value.value);
  776.     })();
  777.  
  778.     function Poliz() {
  779.         this.code = [];
  780.         this.valiables = [];
  781.         this.valiableNames = {};
  782.     }
  783.  
  784.     Poliz.prototype = {
  785.         getCodeLength() {
  786.             return this.code.length;
  787.         },
  788.         popCodeForLength(length) {
  789.             while (this.code.length > length) {
  790.                 this.code.pop();
  791.             }
  792.         },
  793.         addRecord(type, value) {
  794.             let index = this.code.length;
  795.             let record = { type: type, value: value };
  796.             this.code.push(record);
  797.             return index;
  798.         },
  799.         addCommand(command) {
  800.             return this.addRecord(PolizRecordType.Command, command.index);
  801.         },
  802.         addVariable(name) {
  803.             if (this.valiableNames[name] == undefined) {
  804.                 this.valiableNames[name] = this.valiables.length;
  805.                 this.valiables.push(name);
  806.             }
  807.             return this.addRecord(PolizRecordType.Variable, this.valiableNames[name]);
  808.         },
  809.         addConst(value) {
  810.             return this.addRecord(PolizRecordType.Const, value);
  811.         },
  812.         addPointer(index) {
  813.             return this.addRecord(PolizRecordType.Pointer, index);
  814.         },
  815.         updateValue(index, newValue) {
  816.             if (index < this.code.length) {
  817.                 this.code[index].value = newValue;
  818.             }
  819.         }
  820.     };
  821. </script>
  822. <!-- SintAnalizer -->
  823. <script>
  824.     function SintAnalizer() {
  825.         this.lexList = [];
  826.         this.currentLexIndex = 0;
  827.         this.currentLex = {};
  828.         this.output = {};
  829.         this.poliz = new Poliz();
  830.     }
  831.  
  832.     SintAnalizer.prototype = {
  833.         SetLexIndex(i) {
  834.             this.currentLexIndex = i;
  835.             this.currentLex = this.lexList[this.currentLexIndex];
  836.             //console.log(`${this.currentLexIndex}) ${JSON.stringify(this.currentLex)}`);
  837.         },
  838.         FirstLex() {
  839.             this.SetLexIndex(0);
  840.         },
  841.         NextLex() {
  842.             this.SetLexIndex(this.currentLexIndex + 1);
  843.         },
  844.         PrevLex() {
  845.             this.SetLexIndex(this.currentLexIndex - 1);
  846.         },
  847.         Error(expected) {
  848.             let text = `Incorrect char on position ${this.currentLex.position.start}. Expected (${JSON.stringify(expected)}) but has "${this.currentLex.class}"`;
  849.             throw new Error(text);
  850.         },
  851.         GenerateNode(value, type, pos) {
  852.             let node = {
  853.                 value: value,
  854.                 type: type,
  855.                 position: pos.start,
  856.                 nodes: [],
  857.                 UpdateValueByNodes() {
  858.                     if (this.nodes.length < 1) {
  859.                         return this.value;
  860.                     }
  861.  
  862.                     let nodesValues = this.nodes.map(n => n.UpdateValueByNodes());
  863.                     let newValue = nodesValues.join(' ');
  864.                     this.value = newValue;
  865.                     return newValue;
  866.                 }
  867.             };
  868.             return node;
  869.         },
  870.         GeneratePosNode(value, type) {
  871.             let node = this.GenerateNode(value, type, this.currentLex.position);
  872.             return node;
  873.         },
  874.         GenerateTypeNode(type) {
  875.             let node = this.GenerateNode('none', type, this.currentLex.position);
  876.             return node;
  877.         },
  878.         GenerateLexNode() {
  879.             let node = this.GeneratePosNode(this.currentLex.word, this.currentLex.class);
  880.             return node;
  881.         },
  882.         Value(parrentNode) {
  883.             // lex.values.variable
  884.             //  | lex.values.numConst
  885.             //  | lex.separators.bracket.start sint.math lex.separators.bracket.end
  886.             let node = this.GenerateTypeNode(SintClasses.Value);
  887.             let tempIndex = this.currentLexIndex;
  888.  
  889.             if (!this.currentLex) return;
  890.  
  891.             if (this.currentLex.class == LexClasses.separators.bracket.start.value) {
  892.                 let temp = this.GenerateLexNode();
  893.                 node.nodes.push(temp);
  894.                 this.NextLex();
  895.  
  896.                 this.MathOperation(node);
  897.  
  898.                 if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
  899.                     this.Error([LexClasses.separators.bracket.end.value]);
  900.                 }
  901.                 temp = this.GenerateLexNode();
  902.                 node.nodes.push(temp);
  903.                 this.NextLex();
  904.             } else {
  905.                 let inner = undefined;
  906.                 switch (this.currentLex.class) {
  907.                     case LexClasses.values.variable.value:
  908.                         this.poliz.addVariable(this.currentLex.word);
  909.                         inner = this.GenerateLexNode();
  910.                         node.nodes.push(inner);
  911.                         this.NextLex();
  912.                         break;
  913.                     case LexClasses.values.numConst.value:
  914.                         this.poliz.addConst(this.currentLex.word);
  915.                         inner = this.GenerateLexNode();
  916.                         node.nodes.push(inner);
  917.                         this.NextLex();
  918.                         break;
  919.                     default:
  920.                         this.Error([LexClasses.values.variable.value, LexClasses.values.numConst.value]);
  921.                 }
  922.             }
  923.  
  924.             parrentNode.nodes.push(node);
  925.         },
  926.         MathOperation(parrentNode) {
  927.             // sint.value lex.operations.math sint.math
  928.             //  | sint.value
  929.             let node = this.GenerateTypeNode(SintClasses.MathOperation);
  930.  
  931.             this.Value(node);
  932.  
  933.             if (this.currentLex && this.currentLex.class === LexClasses.operations.math.value) {
  934.                 let polizMathCommand = undefined;
  935.                 switch (this.currentLex.word) {
  936.                     case '+':
  937.                         polizMathCommand = PolizCommand.ADD;
  938.                         break;
  939.                     case '-':
  940.                         polizMathCommand = PolizCommand.SUB;
  941.                         break;
  942.                     case '*':
  943.                         polizMathCommand = PolizCommand.MUL;
  944.                         break;
  945.                     case '/':
  946.                         polizMathCommand = PolizCommand.DIV;
  947.                         break;
  948.                     default:
  949.                         throw 'Poliz error!';
  950.                 }
  951.  
  952.                 let temp = this.GenerateLexNode();
  953.                 node.nodes.push(temp);
  954.                 this.NextLex();
  955.  
  956.                 this.MathOperation(node);
  957.  
  958.                 this.poliz.addCommand(polizMathCommand);
  959.             }
  960.  
  961.             parrentNode.nodes.push(node);
  962.         },
  963.         LogicOperation(parrentNode) {
  964.             // lex.separators.bracket.start sint.math lex.operations.compare sint.math lex.separators.bracket.end
  965.             let node = this.GenerateTypeNode(SintClasses.LogicOperation);
  966.  
  967.             if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
  968.                 this.Error([LexClasses.separators.bracket.start.value]);
  969.             }
  970.             let temp = this.GenerateLexNode();
  971.             node.nodes.push(temp);
  972.             this.NextLex();
  973.  
  974.             this.MathOperation(node);
  975.  
  976.             if (this.currentLex.class !== LexClasses.operations.compare.value) {
  977.                 this.Error([LexClasses.operations.compare.value]);
  978.             }
  979.             let polizCompareCommand = undefined;
  980.             switch (this.currentLex.word) {
  981.                 case '<':
  982.                     polizCompareCommand = PolizCommand.CMPL;
  983.                     break;
  984.                 case '<=':
  985.                     polizCompareCommand = PolizCommand.CMPLE;
  986.                     break;
  987.                 case '>':
  988.                     polizCompareCommand = PolizCommand.CMPG;
  989.                     break;
  990.                 case '>=':
  991.                     polizCompareCommand = PolizCommand.CMPGE;
  992.                     break;
  993.                 case '==':
  994.                     polizCompareCommand = PolizCommand.CMPE;
  995.                     break;
  996.                 case '<>':
  997.                     polizCompareCommand = PolizCommand.CMPNE;
  998.                     break;
  999.                 default:
  1000.                     throw 'Poliz error!';
  1001.             }
  1002.             temp = this.GenerateLexNode();
  1003.             node.nodes.push(temp);
  1004.             this.NextLex();
  1005.  
  1006.             this.MathOperation(node);
  1007.  
  1008.             if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
  1009.                 this.Error([LexClasses.separators.bracket.end.value]);
  1010.             }
  1011.             temp = this.GenerateLexNode();
  1012.             node.nodes.push(temp);
  1013.             this.NextLex();
  1014.  
  1015.             this.poliz.addCommand(polizCompareCommand);
  1016.  
  1017.             parrentNode.nodes.push(node);
  1018.         },
  1019.         LogicExpression(parrentNode) {
  1020.             // lex.separators.bracket.start sint.logic.expression lex.operations.logical sint.logic.expression lex.separators.bracket.end
  1021.             //  | sint.logic.operation
  1022.             let node = this.GenerateTypeNode(SintClasses.LogicExpression);
  1023.  
  1024.             let tempIndex = this.currentLexIndex;
  1025.             let polizCodeLen = this.poliz.getCodeLength();
  1026.             try {
  1027.                 this.LogicOperation(node);
  1028.             } catch (error) {
  1029.                 this.SetLexIndex(tempIndex);
  1030.                 this.poliz.popCodeForLength(polizCodeLen);
  1031.                 if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
  1032.                     this.Error([LexClasses.separators.bracket.start.value]);
  1033.                 }
  1034.                 let temp = this.GenerateLexNode();
  1035.                 node.nodes.push(temp);
  1036.                 this.NextLex();
  1037.  
  1038.                 tempIndex = this.currentLexIndex;
  1039.                 lizCodeLen = this.poliz.getCodeLength();
  1040.                 try {
  1041.                     this.LogicExpression(node);
  1042.                 } catch (error) {
  1043.                     this.SetLexIndex(tempIndex);
  1044.                     this.poliz.popCodeForLength(polizCodeLen);
  1045.                     this.LogicOperation(node);
  1046.                 }
  1047.  
  1048.                 if (this.currentLex.class !== LexClasses.operations.logical.value) {
  1049.                     this.Error([LexClasses.operations.logical.value]);
  1050.                 }
  1051.                 let polizLogicCommand = undefined;
  1052.                 switch (this.currentLex.word) {
  1053.                     case 'and':
  1054.                         polizLogicCommand = PolizCommand.AND;
  1055.                         break;
  1056.                     case 'or':
  1057.                         polizLogicCommand = PolizCommand.OR;
  1058.                         break;
  1059.                     default:
  1060.                         throw 'Poliz error!';
  1061.                 }
  1062.                 temp = this.GenerateLexNode();
  1063.                 node.nodes.push(temp);
  1064.                 this.NextLex();
  1065.  
  1066.                 tempIndex = this.currentLexIndex;
  1067.                 lizCodeLen = this.poliz.getCodeLength();
  1068.                 try {
  1069.                     this.LogicExpression(node);
  1070.                 } catch (error) {
  1071.                     this.SetLexIndex(tempIndex);
  1072.                     this.poliz.popCodeForLength(polizCodeLen);
  1073.                     this.LogicOperation(node);
  1074.                 }
  1075.  
  1076.                 if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
  1077.                     this.Error([LexClasses.separators.bracket.end.value]);
  1078.                 }
  1079.                 temp = this.GenerateLexNode();
  1080.                 node.nodes.push(temp);
  1081.                 this.NextLex();
  1082.  
  1083.                 this.poliz.addCommand(polizLogicCommand);
  1084.             }
  1085.  
  1086.             parrentNode.nodes.push(node);
  1087.         },
  1088.         Assignment(parrentNode) {
  1089.             // lex.values.variable lex.operations.as sint.math
  1090.             let node = this.GenerateTypeNode(SintClasses.Assignment);
  1091.  
  1092.             if (this.currentLex.class !== LexClasses.values.variable.value) {
  1093.                 this.Error([LexClasses.values.variable.value]);
  1094.             }
  1095.             this.poliz.addVariable(this.currentLex.word);
  1096.             let temp = this.GenerateLexNode();
  1097.             node.nodes.push(temp);
  1098.             this.NextLex();
  1099.  
  1100.             if (this.currentLex.class !== LexClasses.operations.as.value) {
  1101.                 this.Error([LexClasses.operations.as.value]);
  1102.             }
  1103.             temp = this.GenerateLexNode();
  1104.             node.nodes.push(temp);
  1105.             this.NextLex();
  1106.  
  1107.             this.MathOperation(node);
  1108.  
  1109.             this.poliz.addCommand(PolizCommand.SET);
  1110.  
  1111.             parrentNode.nodes.push(node);
  1112.         },
  1113.         WhileLoop(parrentNode) {
  1114.             // lex.keyword.codeSegment.start lex.keyword.loop.while.start sint.logic.expression [sint.operation] lex.keyword.loop.while.end
  1115.             let node = this.GenerateTypeNode(SintClasses.WhileLoop);
  1116.  
  1117.             let polizLoopStartIndex = this.poliz.getCodeLength();
  1118.  
  1119.             if (this.currentLex.class !== LexClasses.keywords.codeSegment.start.value) {
  1120.                 this.Error([LexClasses.keywords.codeSegment.start.value]);
  1121.             }
  1122.             let temp = this.GenerateLexNode();
  1123.             node.nodes.push(temp);
  1124.             this.NextLex();
  1125.  
  1126.             if (this.currentLex.class !== LexClasses.keywords.loop.while.start.value) {
  1127.                 this.Error([LexClasses.keywords.loop.while.start.value]);
  1128.             }
  1129.             temp = this.GenerateLexNode();
  1130.             node.nodes.push(temp);
  1131.             this.NextLex();
  1132.  
  1133.             this.LogicExpression(node);
  1134.  
  1135.             let polizAfterLoopLabel = this.poliz.addPointer(-1);
  1136.             this.poliz.addCommand(PolizCommand.JZ);
  1137.  
  1138.             while (this.currentLex.class !== LexClasses.keywords.loop.while.end.value) {
  1139.                 this.Operation(node);
  1140.             }
  1141.  
  1142.             if (this.currentLex.class !== LexClasses.keywords.loop.while.end.value) {
  1143.                 this.Error([LexClasses.keywords.loop.while.end.value]);
  1144.             }
  1145.             temp = this.GenerateLexNode();
  1146.             node.nodes.push(temp);
  1147.             this.NextLex();
  1148.  
  1149.             this.poliz.addPointer(polizLoopStartIndex);
  1150.             let polizLastLoopIndex = this.poliz.addCommand(PolizCommand.JMP);
  1151.             this.poliz.updateValue(polizAfterLoopLabel, polizLastLoopIndex + 1);
  1152.  
  1153.             parrentNode.nodes.push(node);
  1154.         },
  1155.         Read(parrentNode) {
  1156.             // lex.keyword.IO.read lex.separators.bracket.start lex.values.variable lex.separators.bracket.end
  1157.             let node = this.GenerateTypeNode(SintClasses.Read);
  1158.  
  1159.             if (this.currentLex.class !== LexClasses.keywords.IO.read.value) {
  1160.                 this.Error([LexClasses.keywords.IO.read.value]);
  1161.             }
  1162.             let temp = this.GenerateLexNode();
  1163.             node.nodes.push(temp);
  1164.             this.NextLex();
  1165.  
  1166.             if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
  1167.                 this.Error([LexClasses.separators.bracket.start.value]);
  1168.             }
  1169.             temp = this.GenerateLexNode();
  1170.             node.nodes.push(temp);
  1171.             this.NextLex();
  1172.  
  1173.             if (this.currentLex.class !== LexClasses.values.variable.value) {
  1174.                 this.Error([LexClasses.values.variable.value]);
  1175.             }
  1176.             this.poliz.addVariable(this.currentLex.word);
  1177.             temp = this.GenerateLexNode();
  1178.             node.nodes.push(temp);
  1179.             this.NextLex();
  1180.  
  1181.             if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
  1182.                 this.Error([LexClasses.separators.bracket.end.value]);
  1183.             }
  1184.             temp = this.GenerateLexNode();
  1185.             node.nodes.push(temp);
  1186.             this.NextLex();
  1187.  
  1188.             this.poliz.addCommand(PolizCommand.READ);
  1189.  
  1190.             parrentNode.nodes.push(node);
  1191.         },
  1192.         Write(parrentNode) {
  1193.             // lex.keyword.IO.write lex.separators.bracket.start sint.math lex.separators.bracket.end
  1194.             let node = this.GenerateTypeNode(SintClasses.Write);
  1195.  
  1196.             if (this.currentLex.class !== LexClasses.keywords.IO.write.value) {
  1197.                 this.Error([LexClasses.keywords.IO.write.value]);
  1198.             }
  1199.             let temp = this.GenerateLexNode();
  1200.             node.nodes.push(temp);
  1201.             this.NextLex();
  1202.  
  1203.             if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
  1204.                 this.Error([LexClasses.separators.bracket.start.value]);
  1205.             }
  1206.             temp = this.GenerateLexNode();
  1207.             node.nodes.push(temp);
  1208.             this.NextLex();
  1209.  
  1210.             this.MathOperation(node);
  1211.  
  1212.             if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
  1213.                 this.Error([LexClasses.separators.bracket.end.value]);
  1214.             }
  1215.             temp = this.GenerateLexNode();
  1216.             node.nodes.push(temp);
  1217.             this.NextLex();
  1218.  
  1219.             this.poliz.addCommand(PolizCommand.WRITE);
  1220.  
  1221.             parrentNode.nodes.push(node);
  1222.         },
  1223.         Operation(parrentNode) {
  1224.             // sint.assignment
  1225.             //  | sint.loop.while
  1226.             //  | sint.read
  1227.             //  | sint.write
  1228.             let node = this.GenerateTypeNode(SintClasses.Operation);
  1229.             switch (this.currentLex.class) {
  1230.                 case LexClasses.values.variable.value:
  1231.                     this.Assignment(node);
  1232.                     break;
  1233.                 case LexClasses.keywords.codeSegment.start.value:
  1234.                     this.WhileLoop(node);
  1235.                     break;
  1236.                 case LexClasses.keywords.IO.read.value:
  1237.                     this.Read(node);
  1238.                     break;
  1239.                 case LexClasses.keywords.IO.write.value:
  1240.                     this.Write(node);
  1241.                     break;
  1242.                 default:
  1243.                     throw this.Error([LexClasses.values.variable.value, LexClasses.keywords.codeSegment.start.value]);
  1244.             }
  1245.             parrentNode.nodes.push(node);
  1246.         },
  1247.         parse(lexems) {
  1248.             this.lexList = lexems;
  1249.             this.poliz = new Poliz();
  1250.             this.FirstLex();
  1251.             this.output = this.GenerateTypeNode(SintClasses.Code);
  1252.             try {
  1253.                 while (this.currentLexIndex < this.lexList.length) {
  1254.                     this.Operation(this.output);
  1255.                 }
  1256.                 this.output.UpdateValueByNodes();
  1257.             } catch (ex) {
  1258.                 alert(ex);
  1259.             }
  1260.         },
  1261.     };
  1262. </script>
  1263. <!-- PolizInterpretator -->
  1264. <script>
  1265.     const PolizInterpretatorSteckValue = {
  1266.         Variable: 'var',
  1267.         Const: 'const',
  1268.         Bool: 'bool',
  1269.         Pointer: 'ptr',
  1270.     };
  1271.  
  1272.     function PolizInterpretator(poliz, output) {
  1273.         this.poliz = poliz;
  1274.         this.execution = {
  1275.             pointer: 0,
  1276.             code: [],
  1277.             stack: [],
  1278.             variables: {}
  1279.         };
  1280.  
  1281.         let context = this;
  1282.  
  1283.         this.output = {
  1284.             container: output,
  1285.             clean() {
  1286.                 this.container.value = '';
  1287.             },
  1288.             writeLine(text) {
  1289.                 this.container.value += `${text}\n`;
  1290.             },
  1291.             writeIn(value) {
  1292.                 this.writeLine(`<< ${value}`);
  1293.             },
  1294.             writeOut(value) {
  1295.                 this.writeLine(`>> ${value}`);
  1296.             },
  1297.             error(text) {
  1298.                 let msg = `Error on pos ${context.execution.pointer}! ${text}`;
  1299.                 this.writeLine(msg);
  1300.                 throw msg;
  1301.             },
  1302.             typeError(type) {
  1303.                 this.error(`Not ${type}!`);
  1304.             }
  1305.         };
  1306.  
  1307.         this.stack = {
  1308.             push(type, value) {
  1309.                 context.execution.stack.push({ type, value });
  1310.             },
  1311.             pushVariable(value) {
  1312.                 this.push(PolizInterpretatorSteckValue.Variable, value);
  1313.             },
  1314.             pushConst(value) {
  1315.                 this.push(PolizInterpretatorSteckValue.Const, value);
  1316.             },
  1317.             pushBool(value) {
  1318.                 this.push(PolizInterpretatorSteckValue.Bool, value);
  1319.             },
  1320.             pushPointer(value) {
  1321.                 this.push(PolizInterpretatorSteckValue.Pointer, value);
  1322.             },
  1323.             pop() {
  1324.                 return context.execution.stack.pop();
  1325.             },
  1326.         };
  1327.  
  1328.         this.valiables = {
  1329.             get(name) {
  1330.                 let val = context.execution.variables[name];
  1331.                 if (val == undefined) {
  1332.                     context.output.error(`Variable "${name}" not exists!`);
  1333.                 }
  1334.                 return val;
  1335.             },
  1336.             set(name, value) {
  1337.                 context.execution.variables[name] = value;
  1338.             }
  1339.         };
  1340.  
  1341.         this.executionHistory = [];
  1342.     }
  1343.  
  1344.     PolizInterpretator.prototype = {
  1345.         clearExecution() {
  1346.             this.execution = {
  1347.                 pointer: 0,
  1348.                 code: JSON.parse(JSON.stringify(this.poliz.code)),
  1349.                 stack: [],
  1350.                 variables: {}
  1351.             };
  1352.         },
  1353.         setPtr(ptr) {
  1354.             this.execution.pointer = ptr;
  1355.         },
  1356.         nextPtr() {
  1357.             this.execution.pointer++;
  1358.         },
  1359.         popValue() {
  1360.             let item = this.stack.pop();
  1361.             if (![PolizInterpretatorSteckValue.Variable, PolizInterpretatorSteckValue.Const].includes(item.type)) {
  1362.                 this.output.typeError(`${PolizInterpretatorSteckValue.Variable} or ${PolizInterpretatorSteckValue.Const}`);
  1363.             }
  1364.  
  1365.             switch (item.type) {
  1366.                 case PolizInterpretatorSteckValue.Variable:
  1367.                     return this.valiables.get(item.value);
  1368.                 case PolizInterpretatorSteckValue.Const:
  1369.                     return +item.value;
  1370.             }
  1371.         },
  1372.         pushHistoryRecord(command) {
  1373.             this.executionHistory.push({
  1374.                 command: command,
  1375.                 stack: JSON.parse(JSON.stringify(this.execution.stack.map(v => v.value))),
  1376.                 variables: JSON.stringify(this.execution.variables),
  1377.             });
  1378.         },
  1379.         executeCommand(command) {
  1380.             switch (command) {
  1381.                 case PolizCommand.JMP.value:
  1382.                     {
  1383.                         let ptr = this.stack.pop();
  1384.                         if (ptr.type !== PolizInterpretatorSteckValue.Pointer) {
  1385.                             this.output.typeError(PolizInterpretatorSteckValue.Pointer);
  1386.                         }
  1387.                         this.setPtr(ptr.value);
  1388.                     }
  1389.                     break;
  1390.                 case PolizCommand.JZ.value:
  1391.                     {
  1392.                         let ptr = this.stack.pop();
  1393.                         if (ptr.type !== PolizInterpretatorSteckValue.Pointer) {
  1394.                             this.output.typeError(PolizInterpretatorSteckValue.Pointer);
  1395.                         }
  1396.                         let cond = this.stack.pop();
  1397.                         if (cond.type !== PolizInterpretatorSteckValue.Bool) {
  1398.                             this.output.typeError(PolizInterpretatorSteckValue.Bool);
  1399.                         }
  1400.                         if (!cond.value) {
  1401.                             this.setPtr(ptr.value);
  1402.                         } else {
  1403.                             this.nextPtr();
  1404.                         }
  1405.                     }
  1406.                     break;
  1407.                 case PolizCommand.SET.value:
  1408.                     {
  1409.                         let value = this.popValue();
  1410.                         let variable = this.stack.pop();
  1411.                         if (variable.type !== PolizInterpretatorSteckValue.Variable) {
  1412.                             this.output.typeError(PolizInterpretatorSteckValue.Variable);
  1413.                         }
  1414.                         this.valiables.set(variable.value, value);
  1415.                         this.nextPtr();
  1416.                     }
  1417.                     break;
  1418.                 case PolizCommand.ADD.value:
  1419.                     {
  1420.                         let value2 = this.popValue();
  1421.                         let value1 = this.popValue();
  1422.                         this.stack.pushConst(value1 + value2);
  1423.                         this.nextPtr();
  1424.                     }
  1425.                     break;
  1426.                 case PolizCommand.SUB.value:
  1427.                     {
  1428.                         let value2 = this.popValue();
  1429.                         let value1 = this.popValue();
  1430.                         this.stack.pushConst(value1 - value2);
  1431.                         this.nextPtr();
  1432.                     }
  1433.                     break;
  1434.                 case PolizCommand.MUL.value:
  1435.                     {
  1436.                         let value2 = this.popValue();
  1437.                         let value1 = this.popValue();
  1438.                         this.stack.pushConst(value1 * value2);
  1439.                         this.nextPtr();
  1440.                     }
  1441.                     break;
  1442.                 case PolizCommand.DIV.value:
  1443.                     {
  1444.                         let value2 = this.popValue();
  1445.                         let value1 = this.popValue();
  1446.                         this.stack.pushConst(value1 / value2);
  1447.                         this.nextPtr();
  1448.                     }
  1449.                     break;
  1450.                 case PolizCommand.AND.value:
  1451.                     {
  1452.                         let cond2 = this.stack.pop();
  1453.                         if (cond2.type !== PolizInterpretatorSteckValue.Bool) {
  1454.                             this.output.typeError(PolizInterpretatorSteckValue.Bool);
  1455.                         }
  1456.                         let cond1 = this.stack.pop();
  1457.                         if (cond1.type !== PolizInterpretatorSteckValue.Bool) {
  1458.                             this.output.typeError(PolizInterpretatorSteckValue.Bool);
  1459.                         }
  1460.                         this.stack.pushBool(cond1.value && cond2.value);
  1461.                         this.nextPtr();
  1462.                     }
  1463.                     break;
  1464.                 case PolizCommand.OR.value:
  1465.                     {
  1466.                         let cond2 = this.stack.pop();
  1467.                         if (cond2.type !== PolizInterpretatorSteckValue.Bool) {
  1468.                             this.output.typeError(PolizInterpretatorSteckValue.Bool);
  1469.                         }
  1470.                         let cond1 = this.stack.pop();
  1471.                         if (cond1.type !== PolizInterpretatorSteckValue.Bool) {
  1472.                             this.output.typeError(PolizInterpretatorSteckValue.Bool);
  1473.                         }
  1474.                         this.stack.pushBool(cond1.value || cond2.value);
  1475.                         this.nextPtr();
  1476.                     }
  1477.                     break;
  1478.                 case PolizCommand.CMPE.value:
  1479.                     {
  1480.                         let value2 = this.popValue();
  1481.                         let value1 = this.popValue();
  1482.                         this.stack.pushBool(value1 == value2);
  1483.                         this.nextPtr();
  1484.                     }
  1485.                     break;
  1486.                 case PolizCommand.CMPNE.value:
  1487.                     {
  1488.                         let value2 = this.popValue();
  1489.                         let value1 = this.popValue();
  1490.                         this.stack.pushBool(value1 != value2);
  1491.                         this.nextPtr();
  1492.                     }
  1493.                     break;
  1494.                 case PolizCommand.CMPL.value:
  1495.                     {
  1496.                         let value2 = this.popValue();
  1497.                         let value1 = this.popValue();
  1498.                         this.stack.pushBool(value1 < value2);
  1499.                         this.nextPtr();
  1500.                     }
  1501.                     break;
  1502.                 case PolizCommand.CMPLE.value:
  1503.                     {
  1504.                         let value2 = this.popValue();
  1505.                         let value1 = this.popValue();
  1506.                         this.stack.pushBool(value1 <= value2);
  1507.                         this.nextPtr();
  1508.                     }
  1509.                     break;
  1510.                 case PolizCommand.CMPG.value:
  1511.                     {
  1512.                         let value2 = this.popValue();
  1513.                         let value1 = this.popValue();
  1514.                         this.stack.pushBool(value1 > value2);
  1515.                         this.nextPtr();
  1516.                     }
  1517.                     break;
  1518.                 case PolizCommand.CMPGE.value:
  1519.                     {
  1520.                         let value2 = this.popValue();
  1521.                         let value1 = this.popValue();
  1522.                         this.stack.pushBool(value1 > value2);
  1523.                         this.nextPtr();
  1524.                     }
  1525.                     break;
  1526.                 case PolizCommand.READ.value:
  1527.                     {
  1528.                         let variable = this.stack.pop();
  1529.                         if (variable.type !== PolizInterpretatorSteckValue.Variable) {
  1530.                             this.output.typeError(PolizInterpretatorSteckValue.Variable);
  1531.                         }
  1532.                         let inputValue = prompt('Enter number:');
  1533.                         this.output.writeIn(inputValue);
  1534.                         if (inputValue == undefined || inputValue.length < 1) {
  1535.                             this.output.error('Input is empty!');
  1536.                         }
  1537.                         inputValue = +inputValue;
  1538.                         if (!Number.isFinite(inputValue)) {
  1539.                             this.output.error('Input value is not number!')
  1540.                         }
  1541.                         this.valiables.set(variable.value, inputValue);
  1542.                         this.nextPtr();
  1543.                     }
  1544.                     break;
  1545.                 case PolizCommand.WRITE.value:
  1546.                     {
  1547.                         let value = this.popValue();
  1548.                         this.output.writeOut(value);
  1549.                         this.nextPtr();
  1550.                     }
  1551.                     break;
  1552.             }
  1553.         },
  1554.         execute() {
  1555.             this.output.clean();
  1556.             this.clearExecution();
  1557.             this.output.writeLine('Start execution.');
  1558.             while (this.execution.pointer < this.execution.code.length) {
  1559.                 const command = this.execution.code[this.execution.pointer];
  1560.                 switch (command.type) {
  1561.                     case PolizRecordType.Command:
  1562.                         let commandName = PolizCommandsList[command.value];
  1563.                         this.pushHistoryRecord(commandName);
  1564.                         this.executeCommand(commandName);
  1565.                         break;
  1566.                     case PolizRecordType.Variable:
  1567.                         let varName = this.poliz.valiables[command.value];
  1568.                         this.pushHistoryRecord(varName);
  1569.                         this.stack.pushVariable(varName);
  1570.                         this.nextPtr();
  1571.                         break;
  1572.                     case PolizRecordType.Const:
  1573.                         this.stack.pushConst(command.value);
  1574.                         this.pushHistoryRecord(command.value);
  1575.                         this.nextPtr();
  1576.                         break;
  1577.                     case PolizRecordType.Pointer:
  1578.                         this.pushHistoryRecord(command.value);
  1579.                         this.stack.pushPointer(command.value);
  1580.                         this.nextPtr();
  1581.                         break;
  1582.                 }
  1583.             }
  1584.  
  1585.             this.output.writeLine('Finish execution.');
  1586.         }
  1587.     };
  1588. </script>
  1589.  
  1590. <script src="http://synset.com/ai/_js/tree.js"></script>
  1591.  
  1592. <script>
  1593.     const lexAnalizerInstance = new LexAnalizer(FullAutomatesList);
  1594.  
  1595.     const sintAnalizerInstance = new SintAnalizer();
  1596.  
  1597.     function drawLexOutputTable(output) {
  1598.         let outputTable = {
  1599.             tag: HTMLTags.Table,
  1600.             type: ItemTypes.Container,
  1601.             attributes: { border: "1" },
  1602.             childs: []
  1603.         };
  1604.  
  1605.         outputTable.childs.push({
  1606.             tag: HTMLTags.TableRow,
  1607.             type: ItemTypes.Container,
  1608.             childs: [
  1609.                 {
  1610.                     tag: HTMLTags.TableData,
  1611.                     type: ItemTypes.Value,
  1612.                     value: 'Значение'
  1613.                 },
  1614.                 {
  1615.                     tag: HTMLTags.TableData,
  1616.                     type: ItemTypes.Value,
  1617.                     value: 'Начальная позиция'
  1618.                 },
  1619.                 {
  1620.                     tag: HTMLTags.TableData,
  1621.                     type: ItemTypes.Value,
  1622.                     value: 'Конечная позиция'
  1623.                 },
  1624.                 {
  1625.                     tag: HTMLTags.TableData,
  1626.                     type: ItemTypes.Value,
  1627.                     value: 'Класс'
  1628.                 },
  1629.             ]
  1630.         });
  1631.  
  1632.         for (const o of output) {
  1633.             outputTable.childs.push({
  1634.                 tag: HTMLTags.TableRow,
  1635.                 type: ItemTypes.Container,
  1636.                 childs: [
  1637.                     {
  1638.                         tag: HTMLTags.TableData,
  1639.                         type: ItemTypes.Value,
  1640.                         value: o.word
  1641.                     },
  1642.                     {
  1643.                         tag: HTMLTags.TableData,
  1644.                         type: ItemTypes.Value,
  1645.                         value: o.position.start
  1646.                     },
  1647.                     {
  1648.                         tag: HTMLTags.TableData,
  1649.                         type: ItemTypes.Value,
  1650.                         value: o.position.end
  1651.                     },
  1652.                     {
  1653.                         tag: HTMLTags.TableData,
  1654.                         type: ItemTypes.Value,
  1655.                         value: o.class
  1656.                     },
  1657.                 ]
  1658.             });
  1659.         }
  1660.  
  1661.         return outputTable;
  1662.     }
  1663.  
  1664.     function drawGraphTable(graphNode) {
  1665.         let curNode = undefined;
  1666.         let value = `(value: "${graphNode.value}", pos: ${graphNode.position}, type: ${graphNode.type})`;
  1667.         let tableAttrs = { border: "1", cellspacing: 0 };
  1668.  
  1669.         if (graphNode.nodes.length > 0) {
  1670.             const nodesList = {
  1671.                 tag: HTMLTags.TableRow,
  1672.                 type: ItemTypes.Container,
  1673.                 childs: []
  1674.             };
  1675.  
  1676.             for (const node of graphNode.nodes) {
  1677.                 nodesList.childs.push({
  1678.                     tag: HTMLTags.TableData,
  1679.                     type: ItemTypes.Container,
  1680.                     attributes: { align: 'center', valign: 'top' },
  1681.                     childs: [
  1682.                         drawGraphTable(node)
  1683.                     ]
  1684.                 });
  1685.             }
  1686.  
  1687.             curNode = {
  1688.                 tag: HTMLTags.Table,
  1689.                 type: ItemTypes.Container,
  1690.                 attributes: tableAttrs,
  1691.                 childs: [
  1692.                     {
  1693.                         tag: HTMLTags.TableRow,
  1694.                         type: ItemTypes.Container,
  1695.                         childs: [
  1696.                             {
  1697.                                 tag: HTMLTags.TableData,
  1698.                                 type: ItemTypes.Value,
  1699.                                 attributes: { colspan: graphNode.nodes.length, align: 'center', valign: 'top' },
  1700.                                 value: value
  1701.                             }
  1702.                         ]
  1703.                     },
  1704.                     nodesList
  1705.                 ]
  1706.             };
  1707.         } else {
  1708.             curNode = {
  1709.                 tag: HTMLTags.Table,
  1710.                 type: ItemTypes.Container,
  1711.                 attributes: tableAttrs,
  1712.                 childs: [
  1713.                     {
  1714.                         tag: HTMLTags.TableRow,
  1715.                         type: ItemTypes.Container,
  1716.                         childs: [
  1717.                             {
  1718.                                 tag: HTMLTags.TableData,
  1719.                                 type: ItemTypes.Value,
  1720.                                 attributes: { align: 'center', valign: 'top' },
  1721.                                 value: value
  1722.                             }
  1723.                         ]
  1724.                     }
  1725.                 ]
  1726.             };
  1727.         }
  1728.  
  1729.         return curNode;
  1730.     }
  1731.  
  1732.     function drawPolizTable(poliz) {
  1733.         let table = {
  1734.             tag: HTMLTags.Table,
  1735.             type: ItemTypes.Container,
  1736.             attributes: { border: "1", cellspacing: 0 },
  1737.             childs: [
  1738.                 {
  1739.                     tag: HTMLTags.TableRow,
  1740.                     type: ItemTypes.Container,
  1741.                     childs: [
  1742.                         {
  1743.                             tag: HTMLTags.TableData,
  1744.                             type: ItemTypes.Value,
  1745.                             attributes: { align: 'center' },
  1746.                             value: 'Index'
  1747.                         },
  1748.                         {
  1749.                             tag: HTMLTags.TableData,
  1750.                             type: ItemTypes.Value,
  1751.                             attributes: { align: 'center' },
  1752.                             value: 'Type'
  1753.                         },
  1754.                         {
  1755.                             tag: HTMLTags.TableData,
  1756.                             type: ItemTypes.Value,
  1757.                             attributes: { align: 'center' },
  1758.                             value: 'Value'
  1759.                         },
  1760.                         {
  1761.                             tag: HTMLTags.TableData,
  1762.                             type: ItemTypes.Value,
  1763.                             attributes: { align: 'center' },
  1764.                             value: 'Details'
  1765.                         },
  1766.                     ]
  1767.                 }
  1768.             ]
  1769.         };
  1770.  
  1771.         poliz.code.forEach((value, index) => {
  1772.             let details = undefined;
  1773.             switch (value.type) {
  1774.                 case PolizRecordType.Variable:
  1775.                     details = poliz.valiables[value.value];
  1776.                     break;
  1777.                 case PolizRecordType.Command:
  1778.                     details = PolizCommandsList[value.value];
  1779.                     break;
  1780.                 case PolizRecordType.Const:
  1781.                 case PolizRecordType.Pointer:
  1782.                     details = value.value;
  1783.                     break;
  1784.             }
  1785.  
  1786.             table.childs.push({
  1787.                 tag: HTMLTags.TableRow,
  1788.                 type: ItemTypes.Container,
  1789.                 childs: [
  1790.                     {
  1791.                         tag: HTMLTags.TableData,
  1792.                         type: ItemTypes.Value,
  1793.                         attributes: { align: 'center' },
  1794.                         value: index
  1795.                     },
  1796.                     {
  1797.                         tag: HTMLTags.TableData,
  1798.                         type: ItemTypes.Value,
  1799.                         attributes: { align: 'center' },
  1800.                         value: value.type
  1801.                     },
  1802.                     {
  1803.                         tag: HTMLTags.TableData,
  1804.                         type: ItemTypes.Value,
  1805.                         attributes: { align: 'center' },
  1806.                         value: value.value + ''
  1807.                     },
  1808.                     {
  1809.                         tag: HTMLTags.TableData,
  1810.                         type: ItemTypes.Value,
  1811.                         attributes: { align: 'center' },
  1812.                         value: details + ''
  1813.                     }
  1814.                 ]
  1815.             });
  1816.         })
  1817.  
  1818.         return table;
  1819.     }
  1820.  
  1821.     document.getElementById('parseButton').onclick = () => {
  1822.         lexAnalizerInstance.analize(IOContainers.input.value);
  1823.         IOContainers.lexOutput.innerHTML = '';
  1824.         IOContainers.lexOutput.append(render(drawLexOutputTable(lexAnalizerInstance.output)));
  1825.  
  1826.         sintAnalizerInstance.parse(lexAnalizerInstance.output);
  1827.         IOContainers.sintOutput.innerHTML = '';
  1828.         IOContainers.sintOutput.append(render(drawGraphTable(sintAnalizerInstance.output)));
  1829.  
  1830.         if (Tree) {
  1831.             function mapToTree(node) {
  1832.                 // if (node.nodes.length < 1) {
  1833.                 //     return {
  1834.                 //         nm: `(value: "${node.value}", pos: ${node.position}, type: ${node.type})`
  1835.                 //     };
  1836.                 // }
  1837.                 let res = {
  1838.                     nm: node.value,
  1839.                     ar: []
  1840.                 };
  1841.  
  1842.                 for (let inner of node.nodes) {
  1843.                     res.ar.push(mapToTree(inner));
  1844.                 }
  1845.  
  1846.                 return res;
  1847.             }
  1848.  
  1849.             let t1 = mapToTree(sintAnalizerInstance.output); // Tree.rand(3, 4, 0.1);
  1850.             let t2 = Tree.getSVG(t1);
  1851.             document.getElementById('sintOutputCanvas').innerHTML = t2;
  1852.         }
  1853.  
  1854.         IOContainers.polizOutput.innerHTML = '';
  1855.         IOContainers.polizOutput.append(render(drawPolizTable(sintAnalizerInstance.poliz)));
  1856.  
  1857.     };
  1858.  
  1859.     function drawPolizHistoryTable(output) {
  1860.         let outputTable = {
  1861.             tag: HTMLTags.Table,
  1862.             type: ItemTypes.Container,
  1863.             attributes: { border: "1" },
  1864.             childs: []
  1865.         };
  1866.  
  1867.         outputTable.childs.push({
  1868.             tag: HTMLTags.TableRow,
  1869.             type: ItemTypes.Container,
  1870.             childs: [
  1871.                 {
  1872.                     tag: HTMLTags.TableData,
  1873.                     type: ItemTypes.Value,
  1874.                     value: 'Step'
  1875.                 },
  1876.                 {
  1877.                     tag: HTMLTags.TableData,
  1878.                     type: ItemTypes.Value,
  1879.                     value: 'Command'
  1880.                 },
  1881.                 {
  1882.                     tag: HTMLTags.TableData,
  1883.                     type: ItemTypes.Value,
  1884.                     value: 'Stack'
  1885.                 },
  1886.                 {
  1887.                     tag: HTMLTags.TableData,
  1888.                     type: ItemTypes.Value,
  1889.                     value: 'Variables'
  1890.                 },
  1891.             ]
  1892.         });
  1893.  
  1894.         for (let i = 0; i < output.length; i++) {
  1895.             const o = output[i];
  1896.             outputTable.childs.push({
  1897.                 tag: HTMLTags.TableRow,
  1898.                 type: ItemTypes.Container,
  1899.                 childs: [
  1900.                     {
  1901.                         tag: HTMLTags.TableData,
  1902.                         type: ItemTypes.Value,
  1903.                         value: i + 1 + ''
  1904.                     },
  1905.                     {
  1906.                         tag: HTMLTags.TableData,
  1907.                         type: ItemTypes.Value,
  1908.                         value: o.command
  1909.                     },
  1910.                     {
  1911.                         tag: HTMLTags.TableData,
  1912.                         type: ItemTypes.Value,
  1913.                         value: o.stack
  1914.                     },
  1915.                     {
  1916.                         tag: HTMLTags.TableData,
  1917.                         type: ItemTypes.Value,
  1918.                         value: o.variables
  1919.                     },
  1920.                 ]
  1921.             });
  1922.         }
  1923.  
  1924.         return outputTable;
  1925.     }
  1926.  
  1927.     document.getElementById('interpretationButton').onclick = () => {
  1928.         //sintAnalizerInstance.poliz.;
  1929.  
  1930.         let interpretator = new PolizInterpretator(sintAnalizerInstance.poliz, IOContainers.interpretationOutput);
  1931.         interpretator.execute();
  1932.  
  1933.         IOContainers.interpretationPath.innerHTML = '';
  1934.         IOContainers.interpretationPath.append(render(drawPolizHistoryTable(interpretator.executionHistory)));
  1935.  
  1936.  
  1937.         // let code = polizObj.code;
  1938.         // IOContainers.interpretationOutput.value = JSON.stringify(polizObj);
  1939.         // const someInput = prompt("Some input:");
  1940.         // alert(someInput);
  1941.     }
  1942. </script>
  1943.  
  1944. </html>
Add Comment
Please, Sign In to add comment