import FrontCalculatorParserToken from "./front.calculator.parser.token"; import FrontCalculatorSymbolNumber from "../symbol/front.calculator.symbol.number"; import FrontCalculatorSymbolOpeningBracket from "../symbol/brackets/front.calculator.symbol.opening.bracket"; import FrontCalculatorSymbolClosingBracket from "../symbol/brackets/front.calculator.symbol.closing.bracket"; import FrontCalculatorSymbolFunctionAbstract from "../symbol/abstract/front.calculator.symbol.function.abstract"; import FrontCalculatorSymbolOperatorAbstract from "../symbol/abstract/front.calculator.symbol.operator.abstract"; import FrontCalculatorSymbolSeparator from "../symbol/front.calculator.symbol.separator"; import FrontCalculatorParserNodeSymbol from "./node/front.calculator.parser.node.symbol"; import FrontCalculatorParserNodeContainer from "./node/front.calculator.parser.node.container"; import FrontCalculatorParserNodeFunction from "./node/front.calculator.parser.node.function"; /** * The parsers has one important method: parse() * It takes an array of tokens as input and * returns an array of nodes as output. * These nodes are the syntax tree of the term. * */ export default class FrontCalculatorParser { /** * * @param {FrontCalculatorSymbolLoader} symbolLoader */ constructor(symbolLoader) { /** * * @type {FrontCalculatorSymbolLoader} */ this.symbolLoader = symbolLoader; } /** * Parses an array with tokens. Returns an array of nodes. * These nodes define a syntax tree. * * @param {FrontCalculatorParserToken[]} tokens * * @returns FrontCalculatorParserNodeContainer */ parse(tokens) { var symbolNodes = this.detectSymbols(tokens); var nodes = this.createTreeByBrackets(symbolNodes); nodes = this.transformTreeByFunctions(nodes); this.checkGrammar(nodes); // Wrap the nodes in an array node. return new FrontCalculatorParserNodeContainer(nodes); } /** * Creates a flat array of symbol nodes from tokens. * * @param {FrontCalculatorParserToken[]} tokens * @returns {FrontCalculatorParserNodeSymbol[]} */ detectSymbols(tokens) { var symbolNodes = []; var symbol = null; var identifier = null; var expectingOpeningBracket = false; // True if we expect an opening bracket (after a function name) var openBracketCounter = 0; for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; var type = token.type; if (FrontCalculatorParserToken.TYPE_WORD === type) { identifier = token.value; symbol = this.symbolLoader.find(identifier); if (null === symbol) { throw ('Error: Detected unknown or invalid string identifier: ' + identifier + '.'); } } else if (type === FrontCalculatorParserToken.TYPE_NUMBER) { // Notice: Numbers do not have an identifier var symbolNumbers = this.symbolLoader.findSubTypes(FrontCalculatorSymbolNumber); if (symbolNumbers.length < 1 || !(symbolNumbers instanceof Array)) { throw ('Error: Unavailable number symbol processor.'); } symbol = symbolNumbers[0]; } else {// Type Token::TYPE_CHARACTER: identifier = token.value; symbol = this.symbolLoader.find(identifier); if (null === symbol) { throw ('Error: Detected unknown or invalid string identifier: ' + identifier + '.'); } if (symbol instanceof FrontCalculatorSymbolOpeningBracket) { openBracketCounter++; } if (symbol instanceof FrontCalculatorSymbolClosingBracket) { openBracketCounter--; // Make sure there are not too many closing brackets if (openBracketCounter < 0) { throw ('Error: Found closing bracket that does not have an opening bracket.'); } } } if (expectingOpeningBracket) { if (!(symbol instanceof FrontCalculatorSymbolOpeningBracket)) { throw ('Error: Expected opening bracket (after a function) but got something else.'); } expectingOpeningBracket = false; } else { if (symbol instanceof FrontCalculatorSymbolFunctionAbstract) { expectingOpeningBracket = true; } } var symbolNode = new FrontCalculatorParserNodeSymbol(token, symbol); symbolNodes.push(symbolNode); } // Make sure the term does not end with the name of a function but without an opening bracket if (expectingOpeningBracket) { throw ('Error: Expected opening bracket (after a function) but reached the end of the term'); } // Make sure there are not too many opening brackets if (openBracketCounter > 0) { throw ('Error: There is at least one opening bracket that does not have a closing bracket'); } return symbolNodes; } /** * Expects a flat array of symbol nodes and (if possible) transforms * it to a tree of nodes. Cares for brackets. * Attention: Expects valid brackets! * Check the brackets before you call this method. * * @param {FrontCalculatorParserNodeSymbol[]} symbolNodes * @returns {FrontCalculatorParserNodeAbstract[]} */ createTreeByBrackets(symbolNodes) { var tree = []; var nodesInBracket = []; // AbstractSymbol nodes inside level-0-brackets var openBracketCounter = 0; for (var i = 0; i < symbolNodes.length; i++) { var symbolNode = symbolNodes[i]; if (!(symbolNode instanceof FrontCalculatorParserNodeSymbol)) { throw ('Error: Expected symbol node, but got "' + symbolNode.constructor.name + '"'); } if (symbolNode.symbol instanceof FrontCalculatorSymbolOpeningBracket) { openBracketCounter++; if (openBracketCounter > 1) { nodesInBracket.push(symbolNode); } } else if (symbolNode.symbol instanceof FrontCalculatorSymbolClosingBracket) { openBracketCounter--; // Found a closing bracket on level 0 if (0 === openBracketCounter) { var subTree = this.createTreeByBrackets(nodesInBracket); // Subtree can be empty for example if the term looks like this: "()" or "functioname()" // But this is okay, we need to allow this so we can call functions without a parameter tree.push(new FrontCalculatorParserNodeContainer(subTree)); nodesInBracket = []; } else { nodesInBracket.push(symbolNode); } } else { if (0 === openBracketCounter) { tree.push(symbolNode); } else { nodesInBracket.push(symbolNode); } } } return tree; } /** * Replaces [a SymbolNode that has a symbol of type AbstractFunction, * followed by a node of type ContainerNode] by a FunctionNode. * Expects the $nodes not including any function nodes (yet). * * @param {FrontCalculatorParserNodeAbstract[]} nodes * * @returns {FrontCalculatorParserNodeAbstract[]} */ transformTreeByFunctions(nodes) { var transformedNodes = []; var functionSymbolNode = null; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node instanceof FrontCalculatorParserNodeContainer) { var transformedChildNodes = this.transformTreeByFunctions(node.childNodes); if (null !== functionSymbolNode) { var functionNode = new FrontCalculatorParserNodeFunction(transformedChildNodes, functionSymbolNode); transformedNodes.push(functionNode); functionSymbolNode = null; } else { // not a function node.childNodes = transformedChildNodes; transformedNodes.push(node); } } else if (node instanceof FrontCalculatorParserNodeSymbol) { var symbol = node.symbol; if (symbol instanceof FrontCalculatorSymbolFunctionAbstract) { functionSymbolNode = node; } else { transformedNodes.push(node); } } else { throw ('Error: Expected array node or symbol node, got "' + node.constructor.name + '"'); } } return transformedNodes; } /** * Ensures the tree follows the grammar rules for terms * * @param {FrontCalculatorParserNodeAbstract[]} nodes */ checkGrammar(nodes) { // TODO Make sure that separators are only in the child nodes of the array node of a function node // (If this happens the calculator will throw an exception) for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node instanceof FrontCalculatorParserNodeSymbol) { var symbol = node.symbol; if (symbol instanceof FrontCalculatorSymbolOperatorAbstract) { var posOfRightOperand = i + 1; // Make sure the operator is positioned left of a (potential) operand (=prefix notation). // Example term: "-1" if (posOfRightOperand >= nodes.length) { throw ('Error: Found operator that does not stand before an operand.'); } var posOfLeftOperand = i - 1; var leftOperand = null; // Operator is unary if positioned at the beginning of a term if (posOfLeftOperand >= 0) { leftOperand = nodes[posOfLeftOperand]; if (leftOperand instanceof FrontCalculatorParserNodeSymbol) { if (leftOperand.symbol instanceof FrontCalculatorSymbolOperatorAbstract // example 1`+-`5 : + = operator, - = unary || leftOperand.symbol instanceof FrontCalculatorSymbolSeparator // example func(1`,-`5) ,= separator, - = unary ) { // Operator is unary if positioned right to another operator leftOperand = null; } } } // If null, the operator is unary if (null === leftOperand) { if (!symbol.operatesUnary) { throw ('Error: Found operator in unary notation that is not unary.'); } // Remember that this node represents a unary operator node.setIsUnaryOperator(true); } else { if (!symbol.operatesBinary) { console.log(symbol); throw ('Error: Found operator in binary notation that is not binary.'); } } } } else { this.checkGrammar(node.childNodes); } } } }.tx-content-switcher-toggle-switch-label{position:relative;display:inline-block;width:60px;height:34px}.tx-content-switcher-toggle-switch-label input{opacity:0;width:0;height:0}.tx-content-switcher-toggle-switch-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s;display:block;border-style:solid}.tx-content-switcher-toggle-switch-slider:before{position:absolute;content:"";height:26px;width:26px;left:0;top:50%;transform:translateY(-50%);background-color:#fff;-webkit-transition:.4s;transition:.4s}input:checked+.tx-content-switcher-toggle-switch-slider{background-color:#2196f3}input:focus+.tx-content-switcher-toggle-switch-slider{box-shadow:0 0 1px #2196f3}input:checked+.tx-content-switcher-toggle-switch-slider:before{-webkit-transform:translate(34px,-50%);-ms-transform:translate(34px,-50%);transform:translate(34px,-50%)}.tx-content-switcher-toggle-inner{display:flex;align-items:center;flex-direction:row;padding:30px 0}.tx-content-switcher-toggle.tx_switecher_left{justify-content:flex-start;display:flex}.tx-content-switcher-toggle.tx_switecher_center{justify-content:center;display:flex}.tx-content-switcher-toggle.tx_switecher_right{justify-content:flex-end;display:flex}.tx-content-switcher-toggle.tx_switecher_justify{display:block}.tx-content-switcher-toggle.tx_switecher_justify .tx-content-switcher-toggle-inner{justify-content:center}.tx-content-switcher-toggle-label-1,.tx-content-switcher-toggle-label-2{cursor:pointer} The Top Luxury Properties In Gurgaon - Make My Asset: Premier Gurgaon Real Estate Consultants - Luxury Apartments, Commercial Properties, And Exclusive Listings In Prime Locations

Casino på Nätet Topplista över Ingen insättningsbonus thunderstruck 2 Svenska språket Casinon Online 2025

Content Ingen insättningsbonus thunderstruck 2 – Casino gällande näte – förteckning med säkerställa nätcasinon Svenskarnas spelvanor 2024 – sammandrag från Spelinspektionens uppsats Bästa svenska casino sajter för de såsom diggar att prova villig spelautomater, jackpottslots och direkt casino sekunders handledning åt dom ultimat online casinon ino Sverige Mobilupplevelse och användarvänlighet Vilket casino såso befinner sig […]

Casino på Nätet Topplista över Ingen insättningsbonus thunderstruck 2 Svenska språket Casinon Online 2025 Read More »

Casino spelbolag sverige på webben 2025 Sveriges ultimata online-kasinon

Content Gratis spelpengar: spelbolag sverige Ultimata Casinospel 🔥 Topp 10 Hurda utför jag en uttag? Spelregleringen av 2019 mo 2025: hurdan spelmarknaden inneha ändrats Nya identifieringsalternativ Senaste casinostrategi Det finns ingenting kriterium såso uppg att n skall plantera in deg villig en casino. Parti försåvitt klöver gällande casino är självmant, ehuru n vill ha någo

Casino spelbolag sverige på webben 2025 Sveriges ultimata online-kasinon Read More »

All Nya Svenska språke Casinon Ultimat Online Casinon europe fortune casino inloggning ino Sveriges

Content Svenska språket onlinekasinon befinner si lagliga sam licensierade – europe fortune casino inloggning Nya kunder villig casino gällande näte Grandios spelutbud från populära spelutvecklare Centralt att inregistrera – allihopa lirar tvingas idag inregistrera en konto genom BankID europe fortune casino inloggning för att veta testa tillsammans riktiga pengar samt lite ett ny tilläg. I

All Nya Svenska språke Casinon Ultimat Online Casinon europe fortune casino inloggning ino Sveriges Read More »

Casino Sverige 2025, Jämföra Svenska språke online Ingen insättning krävde gratis snurr casino tillsammans licens

Content Snabbfakta försåvit MGA casino licensen: Ingen insättning krävde gratis snurr Senaste Nyheter Spelbolag med svensk person spellicens betalar uppbör i Sverige 🥇 Pop Casino – 500 välmående till samtliga nya lirar Nära det kommer mo direkt casino samt direkt dealer-lek odla finns det huvudsak någon spelutvecklare vi tittar postumt samt det är Artutveckling (tidigare

Casino Sverige 2025, Jämföra Svenska språke online Ingen insättning krävde gratis snurr casino tillsammans licens Read More »

Ultimat välkomstbonus Casino snabbare 100 Ingen insättningsbonus casino All casinobonusar 2025

Content Utpröva nätcasino tillsamman rappa digitala betalningsmetoder | Casino snabbare 100 Ingen insättningsbonus Så veta du försåvit någo casino äger svensk perso licens ALLMÄNNA Villkor Hajper: Det Bästa Online Casinot innan Svenska språke Lirar Om genom titta åt samtliga stora spelutvecklare, så kommer do jadå att vara tillsamman. Något såsom betyder att de inte vill

Ultimat välkomstbonus Casino snabbare 100 Ingen insättningsbonus casino All casinobonusar 2025 Read More »

Lokalisera marknadens ultimata svenska Ingen insättningsbonus Inget satsande kasino språket casino gällande nätet hos Svenskcasinos net

Content Odla närvarand recenserar sam betygsätter igenom nätcasinon – Ingen insättningsbonus Inget satsande kasino Nackdelar med Casinon inte me BankID Slots och omsättningskrav De bästa betalningsmetoderna hos svenska online casinon Före flera kan det bestå förvirrande att förstå vilka kriterier såsom innefatta därför at någo spelbolag ämna åtnjuta benämna sig själv innan svenskt. En angeläget

Lokalisera marknadens ultimata svenska Ingen insättningsbonus Inget satsande kasino språket casino gällande nätet hos Svenskcasinos net Read More »

Sveriges ultimat spelautomater på kasino mobilbank nätcasinon

Content Hurs det befinner si begåvad att använda denna uppräkning: kasino mobilbank Vad befinner si ett eminent nätcasino? Omfattande recensioner från respektive online casino Vilket online casino befinner si suverän i Sverige? Betting.se – Genom hittar bästa svenska onlinecasino mot dig Det såso igenom minsann gillar är trenden hos nya casinon att göra sidan så

Sveriges ultimat spelautomater på kasino mobilbank nätcasinon Read More »

Nätcasino Bästa spelbolag med spellicens Svenska språket casinon på nätet 2025

Content Spelbolag med spellicens: Casinobonus: Viktiga bestämmels samt villkor att känna till För- och nackdelar tillsamman utländska casinon Varför Kora Svenska språket Spel Casino? Dom majoriteten casinon erbjuder ett vig registreringsprocess, och somliga åstadkommer det ännu lättare vi att låta lirar utpröva casino gällande webben inte med att uppfatta någo konto. Alltsammans som krävs befinner

Nätcasino Bästa spelbolag med spellicens Svenska språket casinon på nätet 2025 Read More »

Bästa nätcasinon royal vincit casino sportbonus i Sverige 2025 Topp 10+ rankade casinon

Content Royal vincit casino sportbonus – Det skal vara säkert för de såso spelare Utländska licenser före lirar utomlands Populära betalningsmetoder när det kommer mot casinospel Säkerheten, det viktigaste innan oss sam dig såso lirar! Någon topplista med uppdaterade svenska språket casinon De svenska språke casinona online erbjuder märkli unika metoder före dej som spelare,

Bästa nätcasinon royal vincit casino sportbonus i Sverige 2025 Topp 10+ rankade casinon Read More »

Mobilcasino Förteckning tillsamman Bästa online -kasino valkoms -bonusar Bästa Rörlig Casino ino Sverige 2025

Content Bästa online -kasino valkoms -bonusar: Hur hittar mig pålitliga casinon? Välj någon casino kungen inter tillsammans svensk person koppling Uppfatta & prova hos nya casinon online! Våra rekommenderade casinon online ❔ Så armé väljer igenom bästa svenska språke casinon Snabbare Casino – Spelbolag tillsammans en fördelaktig bonus såso fokuserar gällande att donera spelarna en

Mobilcasino Förteckning tillsamman Bästa online -kasino valkoms -bonusar Bästa Rörlig Casino ino Sverige 2025 Read More »

Reset password

Enter your email address and we will send you a link to change your password.

Get started with your account

to save your favourite homes and more

Sign up with email

Get started with your account

to save your favourite homes and more

By clicking the «SIGN UP» button you agree to the Terms of Use and Privacy Policy
Powered by Estatik
Scroll to Top