public Service1(ConstructionContext <string> context) { _implementationType = context.ImplementationType; _serviceType = context.ServiceType; _recipientType = context.RecipientType; ExtraData = context.Extra ?? string.Empty; }
// expression is parsed using modified Dijkstra's shunting-yard algorithm. TreeNode ParseExpression(ConstructionContext context, params char[] stopSymbols) { Stack <TreeNode> termStack = new Stack <TreeNode>(); Stack <BinaryOperatorOperation> operatorStack = new Stack <BinaryOperatorOperation>(); termStack.Push(ParseTermWithPossibleFactorial(context)); // expression should have at least one term // then there should be exactly one binary operator and one term every iteration while (context.TryPeekNextToken(out Token token)) { if (token is SymbolToken symbolToken) { if (ParseRules.IsBinaryOperatorChar(symbolToken.Symbol)) { context.EatLastToken(); // eat binary operator BinaryOperatorOperation curOperation = BinaryOperatorOperation.OperatorDictionary[symbolToken.Symbol.ToString()]; while (operatorStack.Count > 0) { BinaryOperatorOperation topOperation = operatorStack.Peek(); if ((topOperation.Precedence > curOperation.Precedence) || (topOperation.Precedence == curOperation.Precedence) && topOperation.IsLeftAssociative) { PopOperatorAndPushResult(termStack, operatorStack); } else { break; } } operatorStack.Push(curOperation); termStack.Push(ParseTermWithPossibleFactorial(context)); continue; } else if (stopSymbols.Contains(symbolToken.Symbol)) { while (operatorStack.Count > 0) { PopOperatorAndPushResult(termStack, operatorStack); } return(termStack.Pop()); } } throw new Exception(String.Format("Unexpected token: '{0}', expected binary operator or stop-symbol", token)); } if (stopSymbols.Length > 0) { throw new Exception(String.Format("Unfinished expression: expected stop symbol '{0}'", stopSymbols[0])); } while (operatorStack.Count > 0) { PopOperatorAndPushResult(termStack, operatorStack); } return(termStack.Pop()); }
internal void MergeWith(ConstructionContext constructionContext) { foreach (var element in constructionContext.series) { if (!this.series.Contains(element)) { this.series.Add(element); } } }
// stupid factorial. Why should it be after term, not before it? TreeNode ParseTermWithPossibleFactorial(ConstructionContext context) { TreeNode term = ParseTerm(context); while (context.TryPeekNextToken(out Token factorialToken) && factorialToken is SymbolToken factorialSymbolToken && factorialSymbolToken.Symbol == '!') { context.EatLastToken(); // eat factorial token term = new UnaryOperationTreeNode(UnaryOperation.Factorial, term); } return(term); }
internal static Service3 CreateService3WithContext(ConstructionContext <int> unused) => new Service3();
internal static object WeakCreate(ConstructionContext <Guid> context) { return(StrongCreate(context)); }
internal static ClassCreatedWithAContext StrongCreate(ConstructionContext <Guid> context) { var service = new ClassCreatedWithAContext(context); return(service); }
private ClassCreatedWithAContext(ConstructionContext <Guid> context) { Context = context; }
internal static Service2 CreateService2WithContext(ConstructionContext <string> context) => new Service2(context.Extra);
internal static Service1 CreateService1WithContext(ConstructionContext <string> context) => new Service1(context);
public TreeNode BuildTree(ConstructionContext context) { List <TreeNode> parameters = new List <TreeNode>(); List <TreeNode> expressions = new List <TreeNode>(); var statements = new List <TreeNode>(); FunctionTreeNode func; string name = "Undefined"; string expressionName = "Undefined"; for (int i = 0; i < context.tokens.Length; ++i) { context.TryGetNextToken(out Token token); switch (token) { case IdentifierToken identifierToken: //maybe add check for defined functions name = identifierToken.ToString(); //if we here, its function break; case NumberToken numberToken: parameters.Add(new NumberTreeNode(int.Parse(numberToken.ToString()))); break; case StringToken stringToken: parameters.Add(new StringTreeNode(stringToken.ToString())); break; case SymbolToken symbolToken: break; case KeywordToken keywordToken: name = keywordToken.ToString(); if (context.TryGetNextToken(out Token tok)) { if (tok.ToString() == "(") { for (; ;) //read arguments { context.TryGetNextToken(out Token token1); if (token1 is NumberToken) { parameters.Add(new NumberTreeNode(int.Parse(token1.ToString()))); } else if (token1.ToString() == ",") { } else if (token1.ToString() == ")") { break; } else { throw new ArgumentException($"Unexpected parameter {token1.ToString()}"); } } } context.TryGetNextToken(out Token tok2); if (tok2 == null) { throw new ArgumentException($"Must be open and close brackets in \"{name}\" cycle"); } else if (tok2.ToString() == "{") { for (; ;) //read expressions { if (context.TryGetNextToken(out Token token1)) { switch (token1) { case IdentifierToken identifierToken: expressionName = identifierToken.ToString(); break; case NumberToken numberToken: expressions.Add(new NumberTreeNode(int.Parse(numberToken.ToString()))); break; case StringToken stringToken: expressions.Add(new StringTreeNode(stringToken.ToString())); break; case SymbolToken symbolToken: if (symbolToken.ToString() == ")") { statements.Add(new FunctionTreeNode(expressionName, expressions.ToArray())); expressions.Clear(); } break; } } if (token1 == null) { //throw new ArgumentException($"Unexpected token \"{token1}\""); throw new ArgumentException($"Need close brace!"); } if (token1.ToString() == "}") { return(new CycleTreeNode(name, statements.ToArray(), parameters.ToArray())); } //else //throw new ArgumentException($"Unexpected expression in cycle {token1.ToString()}"); } } else { throw new ArgumentException($"Unexpected expression{tok2.ToString()}"); } } else { throw new ArgumentException($"Cycle \"{name}\" must be have open and close braces"); //when we have Repeat without brackets } default: throw new ArgumentException($"Something wrong in your code {token}"); } } func = new FunctionTreeNode(name, parameters.ToArray()); return(func); }
public TreeNode Construct(Token[] tokens) { ConstructionContext context = new ConstructionContext(tokens); return(BuildTree(context)); }
TreeNode ParseTerm(ConstructionContext context) { if (!context.TryGetNextToken(out Token token)) { throw new Exception("No tokens for term to parse"); } switch (token) { case SymbolToken symbolToken: { // (expression) if (symbolToken.Symbol == '(') { TreeNode node = ParseExpression(context, ')'); context.EatLastToken(); // eat right brackets return(node); } // |expression| else if (symbolToken.Symbol == '|') { TreeNode node = ParseExpression(context, '|'); context.EatLastToken(); // eat right brackets return(new UnaryOperationTreeNode(UnaryOperation.AbsoluteValue, node)); } // -term else if (symbolToken.Symbol == '-') { return(new UnaryOperationTreeNode(UnaryOperation.Negative, ParseTermWithPossibleFactorial(context))); } // +term else if (symbolToken.Symbol == '+') { return(ParseTermWithPossibleFactorial(context)); } throw new Exception(String.Format("Unexpected symbol token when parsing term: '{0}'", symbolToken.Symbol)); } case IdentifierToken identifierToken: { // variable if (!context.TryPeekNextToken(out Token nextToken)) { return(new UndefinedVariableTreeNode(identifierToken.Identifier)); } else if (!(nextToken is SymbolToken nextSymbolToken && nextSymbolToken.Symbol == '(')) { return(new UndefinedVariableTreeNode(identifierToken.Identifier)); } // if we are here, then it's a function context.EatLastToken(); // eat left brackets // check if it has any parameters // func() if (context.TryPeekNextToken(out Token emptyFuncToken) && emptyFuncToken is SymbolToken emptyFuncSymbolToken && emptyFuncSymbolToken.Symbol == ')') { context.EatLastToken(); // eat right brackets return(new UndefinedFunctionTreeNode(identifierToken.Identifier, new TreeNode[0])); } // parse each parameter // func(expression, ...) List <TreeNode> parameters = new List <TreeNode>(); while (true) { TreeNode parameter = ParseExpression(context, ',', ')'); parameters.Add(parameter); if (context.TryGetNextToken(out Token delimToken) && delimToken is SymbolToken delimSymbolToken) { if (delimSymbolToken.Symbol == ',') { continue; } if (delimSymbolToken.Symbol == ')') { break; } throw new Exception(String.Format("Can't parse function (unknown delimeter token '{0}')", delimSymbolToken)); } } return(new UndefinedFunctionTreeNode(identifierToken.Identifier, parameters.ToArray())); } // literal case NumberToken numberToken: { return(new NumberTreeNode(numberToken.Value)); } } throw new Exception(String.Format("Unknown token type: '{0}'", token)); }