Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <title>Poliz</title>
- </head>
- <body>
- <textarea id="input" cols="60" rows="10"></textarea>
- <button id="parseButton">parse</button>
- <br>
- <details>
- <summary>Лексемы</summary>
- <div id="lexOutputContainer"></div>
- </details>
- <br>
- <details>
- <summary>Синтаксическое дерево</summary>
- <div id="sintOutputContainer"></div>
- <br>
- <br>
- <div id="sintOutputCanvas" width="100%" height="1000px"
- style="vertical-align:top;text-anchor:middle;font-family:monospace;font-size:16px;"></div>
- </details>
- <br>
- <details open>
- <summary>Полиз</summary>
- <div id="polizOutputContainer"></div>
- </details>
- </body>
- <!-- IO -->
- <script>
- const IOContainers = {
- input: document.getElementById('input'),
- lexOutput: document.getElementById('lexOutputContainer'),
- sintOutput: document.getElementById('sintOutputContainer'),
- polizOutput: document.getElementById('polizOutputContainer'),
- };
- IOContainers.input.value =
- `a = 1
- b = 2
- c = 3
- do while (((a < b) and (a <= c)) or (a > c))
- b=b+c
- b=b+a-20
- loop`;
- </script>
- <!-- Automate engine -->
- <script>
- function distinct(array) {
- return array.filter((value, index) => array.indexOf(value) == index);
- }
- (function () {
- let automateExample = {
- states: {
- list: ['a', 'b', 'c'],
- start: 'a',
- end: ['c']
- },
- alphabet: [1, 2, 3],
- translations: [
- { from: 'a', to: 'b', when: 1 },
- { from: 'b', to: 'c', when: 2 },
- { from: 'b', to: 'a', when: 2 },
- { from: 'a', to: 'c', when: 3 },
- ],
- epsilon: {
- useEpsilon: true,
- translations: [
- { from: 'b', to: 'a' },
- { from: 'b', to: 'b' },
- ],
- },
- config: {
- drowWhenNoTranslation: false,
- logEpsilonSeparately: true
- }
- };
- })();
- function validateAutomateTemplate(automateTemplate) {
- if (!automateTemplate) {
- throw new Error(`Template error! Input is undefined.`);
- }
- // --- --- States --- ---
- if (!automateTemplate.states) {
- throw new Error(`States error! States object is empty.`);
- }
- // --- list ---
- if (!automateTemplate.states.list) {
- throw new Error(`States error! States list is undefined.`);
- }
- if (automateTemplate.states.list.length < 1) {
- throw new Error(`States error! States list is empty.`);
- }
- // --- end list ---
- // --- start ---
- if (!automateTemplate.states.start) {
- throw new Error(`Start state error! Start state is undefined.`);
- }
- if (!automateTemplate.states.list.includes(automateTemplate.states.start)) {
- throw new Error(`Start state error! States not include '${automateTemplate.states.start}'.`);
- }
- // --- end start ---
- // --- end ---
- if (!automateTemplate.states.end) {
- throw new Error(`End states error! End states is undefined.`);
- }
- if (automateTemplate.states.end.length < 1) {
- throw new Error(`End states error! End states list is empty.`);
- }
- for (const state of automateTemplate.states.end) {
- if (!automateTemplate.states.list.includes(state)) {
- throw new Error(`End states error! States not include '${state}'.`);
- }
- }
- // --- end end ---
- // --- --- end States --- ---
- // --- --- Alphabet --- ---
- if (!automateTemplate.alphabet) {
- throw new Error(`Alphabet error! Alphabet is undefined.`);
- }
- if (automateTemplate.alphabet.length < 1) {
- throw new Error(`Alphabet error! Alphabet list is empty.`);
- }
- // --- --- end Alphabet --- ---
- // --- --- Translation --- ---
- if (!automateTemplate.translations) {
- throw new Error(`Translation error! Translations is undefined.`);
- }
- if (automateTemplate.translations.length < 1) {
- throw new Error(`Translation error! Translations list is empty.`);
- }
- for (const translation of automateTemplate.translations) {
- if (!automateTemplate.states.list.includes(translation.from)) {
- throw new Error(`Translation error! States not include 'from' value '${translation.from}' on transtalion ${JSON.stringify(translation)}.`);
- }
- if (!automateTemplate.states.list.includes(translation.to)) {
- throw new Error(`Translation error! States not include 'to' value '${translation.to}' on transtalion ${JSON.stringify(translation)}.`);
- }
- if (!automateTemplate.alphabet.includes(translation.when)) {
- throw new Error(`Translation error! Alphabet not include 'when' value '${translation.when}' on transtalion ${JSON.stringify(translation)}.`);
- }
- }
- // --- --- end Translation --- ---
- // --- --- Epsilon --- ---
- if (!automateTemplate.epsilon) {
- throw new Error(`Epsilon error! Epsilon is undefined.`);
- }
- if (automateTemplate.epsilon.useEpsilon) {
- if (!automateTemplate.epsilon.translations) {
- throw new Error(`Epsilon error! Epsilon translations is undefined.`);
- }
- if (automateTemplate.epsilon.translations.length < 1) {
- throw new Error(`Epsilon error! Epsilon translations list is empty.`);
- }
- for (const translation of automateTemplate.epsilon.translations) {
- if (!automateTemplate.states.list.includes(translation.from)) {
- throw new Error(`Epsilon error! States not include 'from' value '${translation.from}' on epsilon transtalion ${JSON.stringify(translation)}.`);
- }
- if (!automateTemplate.states.list.includes(translation.to)) {
- throw new Error(`Epsilon error! States not include 'to' value '${translation.to}' on epsilon transtalion ${JSON.stringify(translation)}.`);
- }
- }
- }
- // --- --- end Epsilon --- ---
- // --- --- Config --- ---
- if (!automateTemplate.config) {
- throw new Error(`Config error! Config is undefined.`);
- }
- // --- --- end Config --- ---
- }
- function Automate(automateTemplate) {
- validateAutomateTemplate(automateTemplate);
- this.automate = {
- states: {
- list: Array.from(automateTemplate.states.list),
- start: automateTemplate.states.start,
- end: Array.from(automateTemplate.states.end)
- },
- alphabet: Array.from(automateTemplate.alphabet),
- translations: {},
- epsilon: {
- useEpsilon: false,
- translations: {}
- },
- config: {
- drowWhenNoTranslation: automateTemplate.config.drowWhenNoTranslation,
- logEpsilonSeparately: automateTemplate.config.logEpsilonSeparately
- }
- };
- for (const state of this.automate.states.list) {
- this.automate.translations[state] = {};
- for (const letter of this.automate.alphabet) {
- this.automate.translations[state][letter] = [];
- }
- }
- for (const translation of automateTemplate.translations) {
- if (this.automate.translations[translation.from][translation.when].includes(translation.to)) {
- throw new Error(`Translation error! Transtalion ${JSON.stringify(translation)} already exists.`);
- }
- this.automate.translations[translation.from][translation.when].push(translation.to);
- }
- if (automateTemplate.epsilon.useEpsilon) {
- this.automate.epsilon.useEpsilon = true;
- for (const state of this.automate.states.list) {
- this.automate.epsilon.translations[state] = [];
- }
- for (const translation of automateTemplate.epsilon.translations) {
- if (this.automate.epsilon.translations[translation.from].includes(translation.to)) {
- throw new Error(`Epsilon translation error! Epsilon transtalion ${JSON.stringify(translation)} already exists.`);
- }
- this.automate.epsilon.translations[translation.from].push(translation.to);
- }
- }
- this.execution = {
- current: [this.automate.states.start],
- log: [],
- errors: []
- };
- }
- Automate.prototype = {
- clearExecution() {
- this.execution = {
- current: [this.automate.states.start],
- log: [],
- errors: []
- };
- this.logStep(null);
- },
- logStep(letter) {
- this.execution.log.push({
- getLetter: letter,
- resultStates: Array.from(this.execution.current)
- });
- },
- processEpsilon() {
- if (!this.automate.epsilon.useEpsilon) {
- return;
- }
- let next = [...this.execution.current];
- let currentChars = this.execution.current;
- let nextChars = [];
- while (currentChars.length > 0) {
- for (let curChar of currentChars) {
- nextChars.push(...this.automate.epsilon.translations[curChar]);
- }
- next.push(...nextChars);
- currentChars = distinct(nextChars).filter(value => !next.includes(value));
- nextChars = [];
- }
- this.execution.current = distinct(next);
- if (this.automate.config.logEpsilonSeparately) {
- this.logStep('epsilon');
- }
- },
- processLetter(letter) {
- if (!this.automate.alphabet.includes(letter)) {
- alert(`Input error! Alphabet not include ${letter}`);
- return;
- }
- let next = [];
- for (let currentState of this.execution.current) {
- let nextStates = this.automate.translations[currentState][letter];
- if (nextStates.length < 1) {
- let error = `No translation for ${JSON.stringify({ from: currentState, when: letter })}`;
- this.execution.errors.push(error);
- if (this.automate.config.drowWhenNoTranslation) {
- throw error;
- } else {
- nextStates = [currentState];
- }
- }
- next.push(...nextStates);
- }
- this.execution.current = distinct(next);
- if (this.automate.config.logEpsilonSeparately) {
- this.logStep(letter);
- this.processEpsilon();
- } else {
- this.processEpsilon();
- this.logStep(letter);
- }
- },
- isComplete() {
- return this.execution.current.some(value => this.automate.states.end.includes(value));
- }
- };
- </script>
- <!-- Lex classes -->
- <script>
- const LexClasses = {
- keywords: {
- loop: {
- while: {
- start: { value: 'lex.keyword.loop.while.start', priority: 1 },
- end: { value: 'lex.keyword.loop.while.end', priority: 1 },
- }
- },
- codeSegment: {
- start: { value: 'lex.keyword.codeSegment.start', priority: 2 },
- end: { value: 'lex.keyword.codeSegment.end', priority: 2 },
- },
- },
- separators: {
- bracket: {
- start: { value: 'lex.separators.bracket.start', priority: 3 },
- end: { value: 'lex.separators.bracket.end', priority: 3 },
- }
- },
- operations: {
- as: { value: 'lex.operations.as', priority: 3 },
- logical: { value: 'lex.operations.logical', priority: 4 },
- compare: { value: 'lex.operations.compare', priority: 4 },
- math: { value: 'lex.operations.math', priority: 4 },
- },
- values: {
- variable: { value: 'lex.values.variable', priority: 5 },
- numConst: { value: 'lex.values.numConst', priority: 5 },
- },
- };
- </script>
- <!-- Automate builder -->
- <script>
- const AutomateBuilder = {
- alphabet: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>=+-*/ ()'.split(''),
- createAutomateTemplate(keyword) {
- let template = {
- states: {
- list: ['start'],
- start: 'start',
- end: [keyword]
- },
- alphabet: AutomateBuilder.alphabet,
- translations: [],
- epsilon: {
- useEpsilon: false,
- translations: [],
- },
- config: {
- drowWhenNoTranslation: true,
- logEpsilonSeparately: false
- }
- };
- let wordPart = '';
- for (const letter of keyword) {
- wordPart += letter;
- const prewState = template.states.list[template.states.list.length - 1];
- const curState = wordPart;
- template.states.list.push(curState);
- template.translations.push({ from: prewState, to: curState, when: letter });
- }
- return template;
- },
- createAutomate(keyword) {
- let template = AutomateBuilder.createAutomateTemplate(keyword);
- let automate = new Automate(template);
- return automate;
- },
- createNumConstAtomate() {
- let template = {
- states: {
- list: ['start', 'num'],
- start: 'start',
- end: ['num']
- },
- alphabet: AutomateBuilder.alphabet,
- translations: [],
- epsilon: {
- useEpsilon: false,
- translations: [],
- },
- config: {
- drowWhenNoTranslation: true,
- logEpsilonSeparately: false
- }
- };
- for (let letter of '123456789') {
- template.translations.push({ from: 'start', to: 'num', when: letter });
- template.translations.push({ from: 'num', to: 'num', when: letter });
- }
- template.translations.push({ from: 'num', to: 'num', when: '0' });
- let automate = new Automate(template);
- return automate;
- },
- createVariableAtomate() {
- let template = {
- states: {
- list: ['start', 'var'],
- start: 'start',
- end: ['var']
- },
- alphabet: AutomateBuilder.alphabet,
- translations: [],
- epsilon: {
- useEpsilon: false,
- translations: [],
- },
- config: {
- drowWhenNoTranslation: true,
- logEpsilonSeparately: false
- }
- };
- for (let letter of 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
- template.translations.push({ from: 'start', to: 'var', when: letter });
- template.translations.push({ from: 'var', to: 'var', when: letter });
- }
- for (let letter of '0123456789') {
- template.translations.push({ from: 'var', to: 'var', when: letter });
- }
- let automate = new Automate(template);
- return automate;
- }
- }
- </script>
- <!-- Automates -->
- <script>
- const FullAutomatesList = {
- // keywords,
- while: {
- automate: AutomateBuilder.createAutomate('while'),
- class: LexClasses.keywords.loop.while.start
- },
- loop: {
- automate: AutomateBuilder.createAutomate('loop'),
- class: LexClasses.keywords.loop.while.end
- },
- do: {
- automate: AutomateBuilder.createAutomate('do'),
- class: LexClasses.keywords.codeSegment.start
- },
- end: {
- automate: AutomateBuilder.createAutomate('end'),
- class: LexClasses.keywords.codeSegment.end
- },
- // end keywords
- // separators
- '(': {
- automate: AutomateBuilder.createAutomate('('),
- class: LexClasses.separators.bracket.start
- },
- ')': {
- automate: AutomateBuilder.createAutomate(')'),
- class: LexClasses.separators.bracket.end
- },
- // end separators
- // operations
- and: {
- automate: AutomateBuilder.createAutomate('and'),
- class: LexClasses.operations.logical
- },
- or: {
- automate: AutomateBuilder.createAutomate('or'),
- class: LexClasses.operations.logical
- },
- '<': {
- automate: AutomateBuilder.createAutomate('<'),
- class: LexClasses.operations.compare
- },
- '>': {
- automate: AutomateBuilder.createAutomate('>'),
- class: LexClasses.operations.compare
- },
- '<=': {
- automate: AutomateBuilder.createAutomate('<='),
- class: LexClasses.operations.compare
- },
- '==': {
- automate: AutomateBuilder.createAutomate('=='),
- class: LexClasses.operations.compare
- },
- '<>': {
- automate: AutomateBuilder.createAutomate('<>'),
- class: LexClasses.operations.compare
- },
- '+': {
- automate: AutomateBuilder.createAutomate('+'),
- class: LexClasses.operations.math
- },
- '-': {
- automate: AutomateBuilder.createAutomate('-'),
- class: LexClasses.operations.math
- },
- '*': {
- automate: AutomateBuilder.createAutomate('*'),
- class: LexClasses.operations.math
- },
- '/': {
- automate: AutomateBuilder.createAutomate('/'),
- class: LexClasses.operations.math
- },
- '=': {
- automate: AutomateBuilder.createAutomate('='),
- class: LexClasses.operations.as
- },
- // end operations
- // values
- variable: {
- automate: AutomateBuilder.createVariableAtomate(),
- class: LexClasses.values.variable
- },
- numConst: {
- automate: AutomateBuilder.createNumConstAtomate(),
- class: LexClasses.values.numConst
- },
- // end values
- }
- </script>
- <!-- Render -->
- <script>
- const HTMLTags = {
- Table: 'table',
- TableRow: 'tr',
- TableData: 'td'
- }
- const ItemTypes = {
- Value: 'VALUE',
- Container: 'CONTAINER'
- }
- function render(item) {
- if (item.element) {
- return item.element;
- }
- let element = document.createElement(item.tag);
- item.element = element;
- if (item.attributes) {
- for (let name in item.attributes) {
- let value = item.attributes[name];
- element.setAttribute(name, value);
- }
- }
- switch (item.type) {
- case ItemTypes.Value:
- if (item.value) {
- element.innerHTML = item.value;
- }
- break;
- case ItemTypes.Container:
- if (item.childs) {
- for (let i in item.childs) {
- let child = item.childs[i];
- if (!child.element) {
- render(child);
- }
- element.append(child.element);
- }
- }
- break;
- }
- return element;
- }
- </script>
- <!-- Lex analizer -->
- <script>
- function LexAnalizer(automatesList) {
- this.automates = automatesList;
- this.output = [];
- this.execution = {
- prevAutomates: [],
- prevCompleteAutomates: [],
- curAutomates: [],
- accumulator: '',
- };
- }
- LexAnalizer.prototype = {
- getAllAutomates() {
- let list = Object.values(this.automates);
- list.sort((a, b) => a.class.priority - b.class.priority);
- list.forEach(element => element.automate.clearExecution());
- return list;
- },
- getCompleteAutomates(automates) {
- return automates.filter(value => value.automate.isComplete());
- },
- resetExecution() {
- this.execution = {
- prevAutomates: this.getAllAutomates(),
- prevCompleteAutomates: null,
- curAutomates: [],
- accumulator: '',
- };
- this.execution.prevCompleteAutomates = this.getCompleteAutomates(this.execution.prevAutomates);
- },
- tryAddToOutput(index) {
- if (this.execution.curAutomates.length < 1) {
- if (this.execution.prevAutomates.length > 0) {
- const lastAutomate = this.execution.prevCompleteAutomates[0];
- if (lastAutomate) {
- this.output.push({
- word: this.execution.accumulator,
- position: {
- start: index - this.execution.accumulator.length,
- end: index - 1
- },
- class: lastAutomate.class.value
- });
- return 3;
- }
- return 2;
- }
- return 1;
- }
- return 0;
- },
- prepareNextStep(letter) {
- this.execution.prevAutomates = this.execution.curAutomates;
- this.execution.prevCompleteAutomates = this.getCompleteAutomates(this.execution.prevAutomates);
- this.execution.curAutomates = [];
- this.execution.accumulator += letter;
- },
- analize(input) {
- const space = ' ';
- this.output = [];
- this.resetExecution();
- input = input.replaceAll(/\s+/g, space);
- for (let i = 0; i < input.length; i++) {
- const letter = input[i];
- for (const automate of this.execution.prevAutomates) {
- try {
- automate.automate.processLetter(letter);
- this.execution.curAutomates.push(automate);
- } catch {
- automate.automate.clearExecution();
- }
- }
- let stepFinished = this.tryAddToOutput(i);
- if (stepFinished) {
- this.resetExecution();
- if (letter != space) {
- i--;
- }
- } else {
- this.prepareNextStep(letter);
- }
- }
- this.tryAddToOutput(input.length);
- }
- };
- </script>
- <!-- Sint classes -->
- <script>
- const SintClasses = {
- Value: 'sint.value',
- // lex.values.variable
- // | lex.values.numConst
- // | lex.separators.bracket.start sint.math lex.separators.bracket.end
- MathOperation: 'sint.math',
- // sint.value lex.operations.math sint.math
- // | sint.value
- LogicOperation: 'sint.logic.operation',
- // lex.separators.bracket.start sint.math lex.operations.compare sint.math lex.separators.bracket.end
- LogicExpression: 'sint.logic.expression',
- // lex.separators.bracket.start sint.logic.expression lex.operations.logical sint.logic.expression lex.separators.bracket.end
- // | sint.logic.operation
- Assignment: 'sint.assignment',
- // lex.values.variable lex.operations.as sint.math
- WhileLoop: 'sint.loop.while',
- // lex.keyword.codeSegment.start lex.keyword.loop.while.start sint.logic.expression [sint.operation] lex.keyword.loop.while.end
- Operation: 'sint.operation',
- // sint.assignment
- // | sint.loop.while
- Code: 'sint.code',
- // [sint.operation]
- };
- </script>
- <!-- Poliz -->
- <script>
- const PolizRecordType = {
- Command: 'prCommand',
- Variable: 'prVariable',
- Const: 'prConst',
- Pointer: 'prPointer',
- };
- const PolizCommand = {
- JMP: { value: 'JMP', index: 0 },
- JZ: { value: 'JZ', index: 1 },
- SET: { value: 'SET', index: 2 },
- ADD: { value: 'ADD', index: 3 },
- SUB: { value: 'SUB', index: 4 },
- MUL: { value: 'MUL', index: 5 },
- DIV: { value: 'DIV', index: 6 },
- AND: { value: 'AND', index: 7 },
- OR: { value: 'OR', index: 8 },
- CMPE: { value: 'CMPE', index: 9 },
- CMPNE: { value: 'CMPNE', index: 10 },
- CMPL: { value: 'CMPL', index: 11 },
- CMPLE: { value: 'CMPLE', index: 12 },
- CMPG: { value: 'CMPG', index: 13 },
- CMPGE: { value: 'CMPGE', index: 14 },
- };
- const PolizCommandsList = (function () {
- let commands = Object.values(PolizCommand);
- commands.sort((a, b) => a.index - b.index);
- return commands.map(value => value.value);
- })();
- function Poliz() {
- this.code = [];
- this.valiables = [];
- this.valiableNames = {};
- }
- Poliz.prototype = {
- getCodeLength() {
- return this.code.length;
- },
- popCodeForLength(length) {
- while (this.code.length > length) {
- this.code.pop();
- }
- },
- addRecord(type, value) {
- let index = this.code.length;
- let record = { type: type, value: value };
- this.code.push(record);
- return index;
- },
- addCommand(command) {
- return this.addRecord(PolizRecordType.Command, command.index);
- },
- addVariable(name) {
- if (!this.valiableNames[name]) {
- this.valiableNames[name] = this.valiables.length;
- this.valiables.push(name);
- }
- return this.addRecord(PolizRecordType.Variable, this.valiableNames[name]);
- },
- addConst(value) {
- return this.addRecord(PolizRecordType.Const, value);
- },
- addPointer(index) {
- return this.addRecord(PolizRecordType.Pointer, index);
- },
- updateValue(index, newValue) {
- if (index < this.code.length) {
- this.code[index].value = newValue;
- }
- }
- };
- </script>
- <!-- SintAnalizer -->
- <script>
- function SintAnalizer() {
- this.lexList = [];
- this.currentLexIndex = 0;
- this.currentLex = {};
- this.output = {};
- this.poliz = new Poliz();
- }
- SintAnalizer.prototype = {
- SetLexIndex(i) {
- this.currentLexIndex = i;
- this.currentLex = this.lexList[this.currentLexIndex];
- //console.log(`${this.currentLexIndex}) ${JSON.stringify(this.currentLex)}`);
- },
- FirstLex() {
- this.SetLexIndex(0);
- },
- NextLex() {
- this.SetLexIndex(this.currentLexIndex + 1);
- },
- PrevLex() {
- this.SetLexIndex(this.currentLexIndex - 1);
- },
- Error(expected) {
- let text = `Incorrect char on position ${this.currentLex.position.start}. Expected (${JSON.stringify(expected)}) but has "${this.currentLex.class}"`;
- throw new Error(text);
- },
- GenerateNode(value, type, pos) {
- let node = {
- value: value,
- type: type,
- position: pos.start,
- nodes: [],
- UpdateValueByNodes() {
- if (this.nodes.length < 1) {
- return this.value;
- }
- let nodesValues = this.nodes.map(n => n.UpdateValueByNodes());
- let newValue = nodesValues.join(' ');
- this.value = newValue;
- return newValue;
- }
- };
- return node;
- },
- GeneratePosNode(value, type) {
- let node = this.GenerateNode(value, type, this.currentLex.position);
- return node;
- },
- GenerateTypeNode(type) {
- let node = this.GenerateNode('none', type, this.currentLex.position);
- return node;
- },
- GenerateLexNode() {
- let node = this.GeneratePosNode(this.currentLex.word, this.currentLex.class);
- return node;
- },
- Value(parrentNode) {
- // lex.values.variable
- // | lex.values.numConst
- // | lex.separators.bracket.start sint.math lex.separators.bracket.end
- let node = this.GenerateTypeNode(SintClasses.Value);
- let tempIndex = this.currentLexIndex;
- if(!this.currentLex) return;
- if (this.currentLex.class == LexClasses.separators.bracket.start.value) {
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
- this.Error([LexClasses.separators.bracket.end.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- } else {
- let inner = undefined;
- switch (this.currentLex.class) {
- case LexClasses.values.variable.value:
- this.poliz.addVariable(this.currentLex.word);
- inner = this.GenerateLexNode();
- node.nodes.push(inner);
- this.NextLex();
- break;
- case LexClasses.values.numConst.value:
- this.poliz.addConst(this.currentLex.word);
- inner = this.GenerateLexNode();
- node.nodes.push(inner);
- this.NextLex();
- break;
- default:
- this.Error([LexClasses.values.variable.value, LexClasses.values.numConst.value]);
- }
- }
- parrentNode.nodes.push(node);
- },
- MathOperation(parrentNode) {
- // sint.value lex.operations.math sint.math
- // | sint.value
- let node = this.GenerateTypeNode(SintClasses.MathOperation);
- this.Value(node);
- if (this.currentLex && this.currentLex.class === LexClasses.operations.math.value) {
- let polizMathCommand = undefined;
- switch (this.currentLex.word) {
- case '+':
- polizMathCommand = PolizCommand.ADD;
- break;
- case '-':
- polizMathCommand = PolizCommand.SUB;
- break;
- case '*':
- polizMathCommand = PolizCommand.MUL;
- break;
- case '/':
- polizMathCommand = PolizCommand.DIV;
- break;
- default:
- throw 'Poliz error!';
- }
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- this.poliz.addCommand(polizMathCommand);
- }
- parrentNode.nodes.push(node);
- },
- LogicOperation(parrentNode) {
- // lex.separators.bracket.start sint.math lex.operations.compare sint.math lex.separators.bracket.end
- let node = this.GenerateTypeNode(SintClasses.LogicOperation);
- if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
- this.Error([LexClasses.separators.bracket.start.value]);
- }
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- if (this.currentLex.class !== LexClasses.operations.compare.value) {
- this.Error([LexClasses.operations.compare.value]);
- }
- let polizCompareCommand = undefined;
- switch (this.currentLex.word) {
- case '<':
- polizCompareCommand = PolizCommand.CMPL;
- break;
- case '<=':
- polizCompareCommand = PolizCommand.CMPLE;
- break;
- case '>':
- polizCompareCommand = PolizCommand.CMPG;
- break;
- case '>=':
- polizCompareCommand = PolizCommand.CMPGE;
- break;
- case '==':
- polizCompareCommand = PolizCommand.CMPE;
- break;
- case '<>':
- polizCompareCommand = PolizCommand.CMPNE;
- break;
- default:
- throw 'Poliz error!';
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
- this.Error([LexClasses.separators.bracket.end.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.poliz.addCommand(polizCompareCommand);
- parrentNode.nodes.push(node);
- },
- LogicExpression(parrentNode) {
- // lex.separators.bracket.start sint.logic.expression lex.operations.logical sint.logic.expression lex.separators.bracket.end
- // | sint.logic.operation
- let node = this.GenerateTypeNode(SintClasses.LogicExpression);
- let tempIndex = this.currentLexIndex;
- let polizCodeLen = this.poliz.getCodeLength();
- try {
- this.LogicOperation(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- this.poliz.popCodeForLength(polizCodeLen);
- if (this.currentLex.class !== LexClasses.separators.bracket.start.value) {
- this.Error([LexClasses.separators.bracket.start.value]);
- }
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- tempIndex = this.currentLexIndex;
- lizCodeLen = this.poliz.getCodeLength();
- try {
- this.LogicExpression(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- this.poliz.popCodeForLength(polizCodeLen);
- this.LogicOperation(node);
- }
- if (this.currentLex.class !== LexClasses.operations.logical.value) {
- this.Error([LexClasses.operations.logical.value]);
- }
- let polizLogicCommand = undefined;
- switch (this.currentLex.word) {
- case 'and':
- polizLogicCommand = PolizCommand.AND;
- break;
- case 'or':
- polizLogicCommand = PolizCommand.OR;
- break;
- default:
- throw 'Poliz error!';
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- tempIndex = this.currentLexIndex;
- lizCodeLen = this.poliz.getCodeLength();
- try {
- this.LogicExpression(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- this.poliz.popCodeForLength(polizCodeLen);
- this.LogicOperation(node);
- }
- if (this.currentLex.class !== LexClasses.separators.bracket.end.value) {
- this.Error([LexClasses.separators.bracket.end.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.poliz.addCommand(polizLogicCommand);
- }
- parrentNode.nodes.push(node);
- },
- Assignment(parrentNode) {
- // lex.values.variable lex.operations.as sint.math
- let node = this.GenerateTypeNode(SintClasses.Assignment);
- if (this.currentLex.class !== LexClasses.values.variable.value) {
- this.Error([LexClasses.values.variable.value]);
- }
- this.poliz.addVariable(this.currentLex.word);
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- if (this.currentLex.class !== LexClasses.operations.as.value) {
- this.Error([LexClasses.operations.as.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- this.poliz.addCommand(PolizCommand.SET);
- parrentNode.nodes.push(node);
- },
- WhileLoop(parrentNode) {
- // lex.keyword.codeSegment.start lex.keyword.loop.while.start sint.logic.expression [sint.operation] lex.keyword.loop.while.end
- let node = this.GenerateTypeNode(SintClasses.WhileLoop);
- let polizLoopStartIndex = this.poliz.getCodeLength();
- if (this.currentLex.class !== LexClasses.keywords.codeSegment.start.value) {
- this.Error([LexClasses.keywords.codeSegment.start.value]);
- }
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- if (this.currentLex.class !== LexClasses.keywords.loop.while.start.value) {
- this.Error([LexClasses.keywords.loop.while.start.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.LogicExpression(node);
- let polizAfterLoopLabel = this.poliz.addPointer(-1);
- this.poliz.addCommand(PolizCommand.JZ);
- while (this.currentLex.class !== LexClasses.keywords.loop.while.end.value) {
- this.Operation(node);
- }
- if (this.currentLex.class !== LexClasses.keywords.loop.while.end.value) {
- this.Error([LexClasses.keywords.loop.while.end.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.poliz.addPointer(polizLoopStartIndex);
- let polizLastLoopIndex = this.poliz.addCommand(PolizCommand.JMP);
- this.poliz.updateValue(polizAfterLoopLabel, polizLastLoopIndex + 1);
- parrentNode.nodes.push(node);
- },
- Operation(parrentNode) {
- // sint.assignment
- // | sint.loop.while
- let node = this.GenerateTypeNode(SintClasses.Operation);
- switch (this.currentLex.class) {
- case LexClasses.values.variable.value:
- this.Assignment(node);
- break;
- case LexClasses.keywords.codeSegment.start.value:
- this.WhileLoop(node);
- break;
- default:
- throw this.Error([LexClasses.values.variable.value, LexClasses.keywords.codeSegment.start.value]);
- }
- parrentNode.nodes.push(node);
- },
- parse(lexems) {
- this.lexList = lexems;
- this.FirstLex();
- this.output = this.GenerateTypeNode(SintClasses.Code);
- try {
- while (this.currentLexIndex < this.lexList.length) {
- this.Operation(this.output);
- }
- this.output.UpdateValueByNodes();
- } catch (ex) {
- alert(ex);
- }
- },
- };
- </script>
- <script src="http://synset.com/ai/_js/tree.js"></script>
- <script>
- const lexAnalizerInstance = new LexAnalizer(FullAutomatesList);
- const sintAnalizerInstance = new SintAnalizer();
- function drawLexOutputTable(output) {
- let outputTable = {
- tag: HTMLTags.Table,
- type: ItemTypes.Container,
- attributes: { border: "1" },
- childs: []
- };
- outputTable.childs.push({
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: 'Значение'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: 'Начальная позиция'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: 'Конечная позиция'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: 'Класс'
- },
- ]
- });
- for (const o of output) {
- outputTable.childs.push({
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: o.word
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: o.position.start
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: o.position.end
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- value: o.class
- },
- ]
- });
- }
- return outputTable;
- }
- function drawGraphTable(graphNode) {
- let curNode = undefined;
- let value = `(value: "${graphNode.value}", pos: ${graphNode.position}, type: ${graphNode.type})`;
- let tableAttrs = { border: "1", cellspacing: 0 };
- if (graphNode.nodes.length > 0) {
- const nodesList = {
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: []
- };
- for (const node of graphNode.nodes) {
- nodesList.childs.push({
- tag: HTMLTags.TableData,
- type: ItemTypes.Container,
- attributes: { align: 'center', valign: 'top' },
- childs: [
- drawGraphTable(node)
- ]
- });
- }
- curNode = {
- tag: HTMLTags.Table,
- type: ItemTypes.Container,
- attributes: tableAttrs,
- childs: [
- {
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { colspan: graphNode.nodes.length, align: 'center', valign: 'top' },
- value: value
- }
- ]
- },
- nodesList
- ]
- };
- } else {
- curNode = {
- tag: HTMLTags.Table,
- type: ItemTypes.Container,
- attributes: tableAttrs,
- childs: [
- {
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center', valign: 'top' },
- value: value
- }
- ]
- }
- ]
- };
- }
- return curNode;
- }
- function drawPolizTable(poliz) {
- let table = {
- tag: HTMLTags.Table,
- type: ItemTypes.Container,
- attributes: { border: "1", cellspacing: 0 },
- childs: [
- {
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: 'Index'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: 'Type'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: 'Value'
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: 'Details'
- },
- ]
- }
- ]
- };
- poliz.code.forEach((value, index) => {
- let details = undefined;
- switch (value.type) {
- case PolizRecordType.Variable:
- details = poliz.valiables[value.value];
- break;
- case PolizRecordType.Command:
- details = PolizCommandsList[value.value];
- break;
- case PolizRecordType.Const:
- case PolizRecordType.Pointer:
- details = value.value;
- break;
- }
- table.childs.push({
- tag: HTMLTags.TableRow,
- type: ItemTypes.Container,
- childs: [
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: index
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: value.type
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: value.value
- },
- {
- tag: HTMLTags.TableData,
- type: ItemTypes.Value,
- attributes: { align: 'center' },
- value: details
- }
- ]
- });
- })
- return table;
- }
- document.getElementById('parseButton').onclick = () => {
- lexAnalizerInstance.analize(IOContainers.input.value);
- IOContainers.lexOutput.innerHTML = '';
- IOContainers.lexOutput.append(render(drawLexOutputTable(lexAnalizerInstance.output)));
- sintAnalizerInstance.parse(lexAnalizerInstance.output);
- IOContainers.sintOutput.innerHTML = '';
- IOContainers.sintOutput.append(render(drawGraphTable(sintAnalizerInstance.output)));
- if (Tree) {
- function mapToTree(node) {
- // if (node.nodes.length < 1) {
- // return {
- // nm: `(value: "${node.value}", pos: ${node.position}, type: ${node.type})`
- // };
- // }
- let res = {
- nm: node.value,
- ar: []
- };
- for (let inner of node.nodes) {
- res.ar.push(mapToTree(inner));
- }
- return res;
- }
- let t1 = mapToTree(sintAnalizerInstance.output); // Tree.rand(3, 4, 0.1);
- let t2 = Tree.getSVG(t1);
- document.getElementById('sintOutputCanvas').innerHTML = t2;
- }
- IOContainers.polizOutput.innerHTML = '';
- IOContainers.polizOutput.append(render(drawPolizTable(sintAnalizerInstance.poliz)));
- };
- </script>
- </html>
Add Comment
Please, Sign In to add comment