Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <title>Sint analizator</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 open>
- <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>
- </body>
- <!-- IO -->
- <script>
- const lexOutputContainer = document.getElementById('lexOutputContainer');
- const sintOutputContainer = document.getElementById('sintOutputContainer');
- const inputElement = document.getElementById('input');
- inputElement.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>
- <!-- SintAnalizer -->
- <script>
- function SintAnalizer() {
- this.lexList = [];
- this.currentLexIndex = 0;
- this.currentLex = {};
- this.output = {};
- }
- 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.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 {
- switch (this.currentLex.class) {
- case LexClasses.values.variable.value:
- case LexClasses.values.numConst.value:
- let 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.class === LexClasses.operations.math.value) {
- let temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- this.MathOperation(node);
- }
- 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]);
- }
- 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();
- 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;
- try {
- this.LogicOperation(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- 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;
- try {
- this.LogicExpression(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- this.LogicOperation(node);
- }
- if (this.currentLex.class !== LexClasses.operations.logical.value) {
- this.Error([LexClasses.operations.logical.value]);
- }
- temp = this.GenerateLexNode();
- node.nodes.push(temp);
- this.NextLex();
- tempIndex = this.currentLexIndex;
- try {
- this.LogicExpression(node);
- } catch (error) {
- this.SetLexIndex(tempIndex);
- 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();
- }
- 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]);
- }
- 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);
- 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);
- 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);
- 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();
- 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;
- }
- document.getElementById('parseButton').onclick = () => {
- lexAnalizerInstance.analize(inputElement.value);
- lexOutputContainer.innerHTML = '';
- lexOutputContainer.append(render(drawLexOutputTable(lexAnalizerInstance.output)));
- sintAnalizerInstance.parse(lexAnalizerInstance.output);
- sintOutputContainer.innerHTML = '';
- sintOutputContainer.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;
- }
- };
- </script>
- </html>
Add Comment
Please, Sign In to add comment