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} Особенности интерфейса Pin-Up: Мобильная версия Vs. Десктопная - Make My Asset: Premier Gurgaon Real Estate Consultants - Luxury Apartments, Commercial Properties, And Exclusive Listings In Prime Locations

Особенности интерфейса Pin-Up: Мобильная версия vs. Десктопная

Особенности интерфейса Pin-Up: Мобильная версия vs. Десктопная

Когда речь заходит об интерфейсах современных онлайн-платформ, Pin-Up выделяется своей продуманностью и удобством использования. Следует понять различия между мобильной и десктопной версиями, чтобы выбрать наиболее подходящий вариант для себя. Основное отличие состоит в оптимизации под конкретные устройства, обеспечивающей уникальный опыт использования как на смартфонах, так и на компьютерах.

Дизайн и эргономика

Дизайн и эргономика — важнейшие аспекты, определяющие комфорт пользователя на любой платформе. Мобильная версия Pin-Up отличается более минималистичным интерфейсом, что позволяет быстрее находить нужные функции. Это особенно важно для пользователей, которые привыкли решать задачи на ходу. Десктопная версия, напротив, может похвастаться более богатым функционалом и широкими возможностями настройки, что подходит для тех, кто проводит много времени за компьютером.

Функциональные различия

Понимание функциональных различий между версиями поможет каждому пользователю определиться с подходящей платформой. В мобильной версии акцент делается на удобство быстрого доступа и простоту использования. Она отлично подходит для тех, кто часто находится в движении и хочет оставаться на связи. Десктопная версия предоставляет полный набор функций, включая расширенные параметры управления и дополнительные сервисы, доступные только на большом экране.

Особенности навигации

Навигация — важная сторона работы с любой платформой. В мобильной версии так и выстроена, чтобы пользователь мог одним касанием найти нужную информацию. Это достигается благодаря интуитивно понятному меню и оптимизированным кнопкам. В десктопной версии навигация представляет собой более сложную систему, что позволяет легко переключаться между различными страницами и функциями. Это особенно актуально для пользователей, работающих в одном окне с несколькими вкладками https://tehnofond.ru/.

Преимущества и недостатки

Каждая из версий Pin-Up имеет свои преимущества и недостатки. Основные преимущества мобильной версии заключаются в:

  1. Легкости и удобстве использования.
  2. Оптимизации для небольших экранов.
  3. Мобильности и доступности вне зависимости от местонахождения.

Недостатки мобильной версии включают ограниченный функционал и необходимость постоянного интернет-соединения. Что касается десктопной версии, её достоинства состоят в:

  1. Широких функциональных возможностях.
  2. Лучшей производительности на стационарных устройствах.
  3. Поддержке мультизадачности и работы в нескольких окнах.

Но при этом десктопная версия ограничена привязкой к стационарному устройству и требовательностью к ресурсам компьютера.

Заключение

Выбор между мобильной и десктопной версиями Pin-Up зависит прежде всего от ваших личных предпочтений и образа жизни. Если вы цените скорость и мобильность, выбирайте мобильную версию. Если вы на первое место ставите функциональность и обширные возможности, десктопная версия станет лучшим выбором. В любом случае, обе версии предлагают пользователям удобный и современный интерфейс, который делает использование платформы приятным и простым.

Часто задаваемые вопросы

Можно ли использовать обе версии одновременно?

Да, вы можете использовать обе версии на разных устройствах, что обеспечивает удобство и гибкость.

Требуется ли отдельная установка для мобильной версии?

Для мобильной версии требуется установка приложения, доступного в официальных магазинах приложений вашего устройства.

Каковы главные критерии выбора между мобильной и десктопной версиями?

Основные критерии — это ваши предпочтения в плане доступности, функциональности и типа устройства, которым вы пользуетесь чаще всего.

Поддерживают ли обе версии синхронизацию данных?

Да, обе версии поддерживают синхронизацию данных, что позволяет вам легко переключаться между устройствами.

Имеются ли ограничения при использовании мобильной версии?

Мобильная версия имеет ограничения в функционале по сравнению с десктопной, так как акцент сделан на удобство и быстродействие.

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