/// <summary> /// Transform a compressed array of tokens into a AST. /// </summary> /// <param name="tokens"></param> /// <returns></returns> public GroupNode BuildAst(IList<Token> tokens) { var context = new NodeContext(); var root = new ParenthesisGroupNode(); context.PushParent(root); BuildGroups(tokens, context); if (context.ParentCount > 1) throw new Exception(); if (context.LastParent != root) throw new Exception(); BuildOperators(root); BuildUnaryBranches(root); BuildBooleanBranches(root); return root; }
private void BuildGroups(IList<Token> tokens, NodeContext context) { for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; switch (token.Type) { case TokenType.Word: { var node = new TermNode(token.Text); context.AddChild(node); } break; case TokenType.BooleanAnd: { var node = new BooleanNode(BooleanType.And); context.AddChild(node); } break; case TokenType.BooleanOr: { var node = new BooleanNode(BooleanType.Or); context.AddChild(node); } break; case TokenType.Operator: { var node = new OperatorNode(token.Text); context.AddChild(node); } break; case TokenType.ParenthesisOpen: { var group = new ParenthesisGroupNode(); context.PushParent(group); } break; case TokenType.ParenthesisClose: { context.PopParent(); } break; case TokenType.Quote: // Quotes should have been removed by BuildSentences(). throw new Exception(); case TokenType.UnaryNot: { var node = new UnaryNode(UnaryType.Not); context.AddChild(node); } break; default: throw new NotImplementedException(); } } }
private void BuildUnaryBranches(ParenthesisGroupNode root) { for (int i = 0; i < root.Count; i++) { if (root[i] is UnaryNode) { if (i == root.Count - 1) throw new Exception(); var unaryNode = (UnaryNode)root[i]; var childNode = root[i + 1]; unaryNode.Child = childNode; if (childNode is ParenthesisGroupNode) { var parenNode = (ParenthesisGroupNode)childNode; BuildUnaryBranches(parenNode); } } else if (root[i] is ParenthesisGroupNode) { var parenNode = (ParenthesisGroupNode)root[i]; BuildUnaryBranches(parenNode); } } }
private void BuildBooleanBranches(ParenthesisGroupNode root) { for (int i = 0; i < root.Count; i++) { if (root[i] is BooleanNode) { if (i == 0 || i == root.Count - 1) throw new Exception(); var booleanNode = (BooleanNode)root[i]; var leftNode = root[i - 1]; var rightNode = root[i + 1]; booleanNode.Add(leftNode); booleanNode.Add(rightNode); --i; // make sure that "i++" will go back to the same value of "i", // which makes us end up on the node after "rightNode". if (rightNode is ParenthesisGroupNode) { var parenNode = (ParenthesisGroupNode)rightNode; BuildBooleanBranches(parenNode); } } else if (root[i] is ParenthesisGroupNode) { var parenNode = (ParenthesisGroupNode)root[i]; BuildBooleanBranches(parenNode); } } }