public ParseNode(ParseToken Token) { if (Token.type == TokenType.SYMBOL) { Value = TruthValue.Unknown; } else { Value = null; } this.Token = Token; Left = null; Right = null; }
/// <summary> /// Given the string of original input, a list of Parse Tokens, and the /// target offender, find the index the token begins and the length of the /// token. /// </summary> /// <param name="Input">Original infix input. </param> /// <param name="List">Sequence of infix tokens. </param> /// <param name="Target">Token to find the start index and length of</param> /// <param name="Start">0 based index in Input were Target begins.</param> /// <param name="Length">Length of target in characters. </param> /// <returns></returns> private static bool FindToken(string Input, List <ParseToken> List, ParseToken Target, out int Start, out int Length) { int cur_ind = 0; foreach (ParseToken pt in List) { cur_ind = Input.IndexOf(pt.symbol, cur_ind); if (pt == Target) { break; } } Start = cur_ind; Length = Target.symbol.Length; return(true); }
/// <summary> /// Break down a string of space delmited input into parse tokens. If a token /// does not follow syntax, a FormatException will be thrown. /// </summary> /// <param name="input">Space delimited input</param> /// <returns></returns> private static List <ParseToken> Tokenize(string input) { List <ParseToken> result = new List <ParseToken>(); string[] toks = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string t in toks) { try { result.Add(ParseToken.Parse(t)); } catch (ArgumentException) { throw new FormatException(string.Format("{0} is not a valid operator or symbol.", t)); } } return(result); }
/// <summary> /// Attempt to parse an RPN sequence of Parse tokens. If successful return the reslting /// tree, else return null and populate the Error and ErrorMessage parameters. /// </summary> /// <param name="Input">RPN sequence of Tokens. </param> /// <param name="Error">Container for Token of Error</param> /// <param name="ErrorMessage">Error message regarding violating token. </param> /// <returns>A binary expression tree if succesful, otherwise null. </returns> public static ParseTree Parse(List <ParseToken> Input, out ParseToken Error, out string ErrorMessage) { Dictionary <string, List <ParseNode> > symbolTable = new Dictionary <string, List <ParseNode> >(); Stack <ParseNode> wSet = new Stack <ParseNode>(); //Stack for processing. ParseNode c; foreach (ParseToken pt in Input) { try { c = new ParseNode(pt); if (c.IsOperator) { //NOT is the only operator that requires //a single operand. if (c.Operation == Operation.NOT) { c.Left = wSet.Pop(); } else { //Right was placed on the stack last //This order does not matter except for IF operators c.Right = wSet.Pop(); c.Left = wSet.Pop(); } //and push it on the stack (fall through) } else { //if its an operand we want to add it to our symbol table. try { symbolTable.Add(c.Token.symbol, new List <ParseNode>() { c }); } catch (ArgumentException) { symbolTable[c.Token.symbol].Add(c); } //Thrown when the key is already present, so at it to the current list. } wSet.Push(c); } catch (InvalidOperationException) { //An operator was not able to pop its needed //operands from the working set. Error = pt; ErrorMessage = string.Format("Too few operands for {0}.", pt.symbol); return(null); } } if (wSet.Count == 0) { //We lost out root? throw new Exception(); } if (wSet.Count > 1) { //If there are still things in the wSet more than //one thing left in the stack there was too many //operands for the operators. while (wSet.Peek().IsOperator&& wSet.Count > 1) { wSet.Pop(); } Error = wSet.Peek().Token; ErrorMessage = string.Format( "Unused operands starting w/ {0}.", wSet.Peek().Token.symbol); return(null); } Error = null; ErrorMessage = null; return(new ParseTree(wSet.Pop(), symbolTable)); }