public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { int idx = (int)q.Take().Type; var match = idx >= 0 && idx < _bitmap.Length && _bitmap[idx]; return(match ? MatchResult.Matched : MatchResult.NoMatch); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { switch (q.Take().Type) { case TokenType.Id: case TokenType.Ties: case TokenType.Variable when AllowVariable: return(MatchResult.Matched); default: return(MatchResult.NoMatch); } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { if (!frame.ProdMatched) { if (_prod == null) { _prod = SqliteGrammar.Prods[ProdName]; } stack.Push(_prod); frame.ProdMatched = true; return(null); } else { return(frame.SubResult); } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { if (frame.OrState == OrTermState.Start) { // try to match the first sub-production stack.Push(Prods[0]); frame.OrState = OrTermState.Match; frame.OrProdIndex = 0; frame.OrStartLoc = q.GetLocation(); return(null); } else if (frame.OrState == OrTermState.Match) { // we have finished matching one of the productions. if it matched, then we're done. if not, move on // to the next production. var result = frame.SubResult; if (result.IsMatch) { return(MatchResult.Matched); } else if (result.ErrorMessage == null) { // no match. rewind to the beginning and retry with the next one. q.Jump(frame.OrStartLoc); frame.OrProdIndex++; if (frame.OrProdIndex >= Prods.Length) { // we have exhausted all of the possibilities and none of them matched. return(MatchResult.NoMatch); } stack.Push(Prods[frame.OrProdIndex]); return(null); } else { // started to match but mismatched past the point of no return. return(result); } } else { throw new Exception($"Unrecognized state: {frame.OrState}"); } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { if (frame.OptionalState == OptionalTermState.Start) { // try to match the sub-production stack.Push(Prod); frame.OptionalState = OptionalTermState.Match; frame.OptionalStartLoc = q.GetLocation(); return(null); } else if (frame.OptionalState == OptionalTermState.Match) { // done matching the sub-production var result = frame.SubResult; if (result.IsMatch) { // the optional term is indeed present. return(MatchResult.Matched); } else if (result.ErrorMessage == null) { // it didn't match but wasn't an error. this is fine, but we do have to walk the cursor back to // where it started since we effectively "matched" zero tokens. q.Jump(frame.OptionalStartLoc); return(MatchResult.Matched); } else { // it started to match but then mismatched past the point of no return. that's an error. return(result); } } else { throw new Exception($"Unrecognized state: {frame.OptionalState}"); } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { System.Diagnostics.Debugger.Break(); return(MatchResult.Matched); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { if (frame.ListState == ListTermState.Start) { frame.ListState = ListTermState.MatchItem; stack.Push(ItemProd); return(null); // -> MatchItem } else if (frame.ListState == ListTermState.MatchSeparator) { var result = frame.SubResult; if (result.IsMatch) { // we have a separator. now try to match the item following it. frame.ListState = ListTermState.MatchItem; stack.Push(ItemProd); return(null); // -> MatchItem } else if (result.ErrorMessage == null) { // we didn't find a separator. this list is done. back up to the beginning of where // the not-separator started and we're done. q.Jump(frame.ListSeparatorStartLoc); if (frame.ListCount < Min) { return(MatchResult.Error( $"At least {Min} list item{(Min == 1 ? " is" : "s are")} required, but only " + $"{frame.ListCount} {(frame.ListCount == 1 ? "was" : "were")} provided. " + $"Expected list item: {ItemProd.GetExpected()}")); } else { return(MatchResult.Matched); } } else { return(result); // error } } else if (frame.ListState == ListTermState.MatchItem) { var result = frame.SubResult; if (result.IsMatch) { // we have an item. is there another? frame.ListCount++; if (SeparatorProd == null) { // there is no separator, so match the next item frame.ListState = ListTermState.MatchItem; frame.ListSeparatorStartLoc = q.GetLocation(); stack.Push(ItemProd); return(null); // -> MatchItem } else { // match separator + item frame.ListState = ListTermState.MatchSeparator; frame.ListSeparatorStartLoc = q.GetLocation(); stack.Push(SeparatorProd); return(null); // -> MatchSeparator } } else if (result.ErrorMessage == null) { if (frame.ListCount == 0) { // the first item might be missing because the list can potentially be optional. return(Min == 0 ? MatchResult.Matched : MatchResult.NoMatch); } else if (SeparatorProd == null) { // there's no separator, so eventually we'll end up here when the list ends. q.Jump(frame.ListSeparatorStartLoc); if (frame.ListCount < Min) { return(MatchResult.Error( $"At least {Min} list item{(Min == 1 ? " is" : "s are")} required, but only " + $"{frame.ListCount} {(frame.ListCount == 1 ? "was" : "were")} provided. " + $"Expected list item: {ItemProd.GetExpected()}")); } else { return(MatchResult.Matched); } } else { // subsequent items must be present because, in the MatchItem state, we've already consumed a // separator so there must be an item following it. return(MatchResult.Error($"Expected list item: {ItemProd.GetExpected()}")); } } else { return(result); // error } } else { throw new Exception($"Unrecognized state: {frame.ListState}"); } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { return(q.Take().Type == TokenType.String ? MatchResult.Matched : MatchResult.NoMatch); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { return(q.Take().Text.ToLower() == Text.ToLower() ? MatchResult.Matched : MatchResult.NoMatch); }
public abstract MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q);
/// <summary> /// Decodes text data using a text table /// </summary> /// <param name="Data">Array of bytes to decode</param> /// <param name="Table">Text table</param> /// <param name="StartTable">Name of the logical table in the text table to start with</param> /// <returns></returns> public static string UsingTable(byte[] Data, Table Table, string StartTable = "{main}", bool ShowAddr = false, uint StartOffset = 0) { var _out = new StringBuilder(); byte[] testseq; var TableStack = new Stack<MatchFrame>(); // tracks which tables have been switched from MatchFrame thisframe = new MatchFrame(Table.LogicalTables[StartTable],0); bool matched; int testloop; // loop pointer for test sequence int remaining = 0; // bytes remaining in _in array // begin loop for all bytes in array passed to this method for (int outerloop = 0; outerloop < Data.Length; ) { // reset the match flag matched = false; // remaining bytes in the data buffer remaining = Data.Length - outerloop; /* Search Loop * 1. Make a byte array beginning with the current byte from the for loop * 2. Add x more elements of bytes ahead of current position, where x is the Byte Width (max number of hex digits in logical table) * 3. Check if this byte sequence is in the control code/table switch/end token lists for this logical table * 4. If not, check if this byte sequence is in the dictionary * 5. If not, go back to 1 with using Byte Width - 1 * 6. When back down to the original single byte, if it is still not found in the lists of the dict, it is not in the table */ // increase testloop by the ByteWidth // ensure that the length of the testseq does not go past the upper bound of _in testloop = thisframe.Table.ByteWidth > remaining ? remaining : thisframe.Table.ByteWidth; // Loop for test byte sequence for (; testloop > 0; testloop--) { // make the testseq as long as testloop and copy that many bytes from _in @ current position (i) testseq = new byte[testloop]; Buffer.BlockCopy(Data, outerloop, testseq, 0, testloop); // check to see if this test sequence matches the previous table switch sequence, if the match mode is -1 if (thisframe.MatchCount == -1 && thisframe.OrigSeq.SequenceEqual<byte>(testseq)) { // then fall back to the previous logical table (match frame) thisframe = TableStack.Pop(); outerloop++; break; } // check each of the dictionaries for the test bytes // table switch if (thisframe.Table.TableSwitches.ContainsKey(testseq)) { // cache the variable for speed var thisswitch = thisframe.Table.TableSwitches[testseq]; TableStack.Push(thisframe); thisframe = new MatchFrame(Table.LogicalTables[thisswitch.TableID], thisswitch.Matches); if (thisframe.MatchCount == -1) thisframe.OrigSeq = testseq; if (thisframe.MatchCount > 0) thisframe.MatchByte = testseq[0]; outerloop += testloop; break; } // control code if (thisframe.Table.ControlCodes.ContainsKey(testseq)) { // NOTE! It is calling the byte comparer EVERY TIME ControlCodes[testseq] is caleld. cache the variable?? // cached variable for speed var thiscode = thisframe.Table.ControlCodes[testseq]; if (thiscode.Params == null) { // this control code has no paramaters, so use quick and easy formatting matched = true; _out.Append('[' + thiscode.Label + ']'); _out.Append(thiscode.Formatting); outerloop += testloop; break; } else { matched = true; int paramoffset = outerloop + testloop; int paramcount = 0; _out.Append('[' + thiscode.Label); foreach (LogicalTable.ControlCode.Parameter thiscodeparam in thiscode.Params) { switch (thiscodeparam.Type) { case LogicalTable.ControlCode.Parameter.NumberType.Hex: _out.Append(' ' + thiscodeparam.Label + "=0x" + Data[paramoffset + paramcount].ToString("X")); break; case LogicalTable.ControlCode.Parameter.NumberType.Decimal: _out.Append(' ' + thiscodeparam.Label + '=' + Data[paramoffset + paramcount].ToString()); break; case LogicalTable.ControlCode.Parameter.NumberType.Binary: _out.Append(' ' + thiscodeparam.Label + '=' + Convert.ToString(Data[paramoffset + paramcount], 2)); break; } paramcount++; } _out.Append(']'); _out.Append(thiscode.Formatting); outerloop += (testloop + paramcount); break; } } // end token if (thisframe.Table.EndTokens.ContainsKey(testseq)) { // cached variable var thistoken = thisframe.Table.EndTokens[testseq]; matched = true; _out.Append("[" + thistoken.Label + "]"); _out.Append(thistoken.Formatting); if (ShowAddr) _out.AppendLine("[0x" + (StartOffset + outerloop + 1).ToString("X") + "]"); outerloop += testloop; break; } // not found among any of the non-standard entries so check standard if (thisframe.Table.StdDict.ContainsKey(testseq)) { matched = true; _out.Append(thisframe.Table.StdDict[testseq]); outerloop += testloop; break; } // if we are down to the last iteration (original byte) and still haven't found anything, the byte isn't found if (testloop == 1) { matched = false; if (TableStack.Count > 0 && thisframe.MatchCount == 0) thisframe = TableStack.Pop(); else { _out.Append("[" + testseq[0].ToString("X2") + "]"); outerloop++; } } } // end of test loop // // if there are match frames on the table stack, let's check for a match and act accordingly if (TableStack.Count > 0) { // matching mode is positive value [with value at 1, the minimum] and there was a match // then return to the previous logical table (matchframe) if (thisframe.MatchCount == 1 && matched) thisframe = TableStack.Pop(); // else if matching mode is positive value [with value greater than 1] and there was a match // then decrease the value by 1 else if (thisframe.MatchCount > 1 && matched) thisframe.Decrease(); } // didn't find nuthin'! } return _out.ToString(); }
/// <summary> /// Decodes text data using a text table /// </summary> /// <param name="Data">Array of bytes to decode</param> /// <param name="Table">Text table</param> /// <param name="StartTable">Name of the logical table in the text table to start with</param> /// <returns></returns> public static string UsingTable(byte[] Data, Table Table, string StartTable = "{main}", bool ShowAddr = false, uint StartOffset = 0) { var _out = new StringBuilder(); byte[] testseq; var TableStack = new Stack <MatchFrame>(); // tracks which tables have been switched from MatchFrame thisframe = new MatchFrame(Table.LogicalTables[StartTable], 0); bool matched; int testloop; // loop pointer for test sequence int remaining = 0; // bytes remaining in _in array // begin loop for all bytes in array passed to this method for (int outerloop = 0; outerloop < Data.Length;) { // reset the match flag matched = false; // remaining bytes in the data buffer remaining = Data.Length - outerloop; /* Search Loop * 1. Make a byte array beginning with the current byte from the for loop * 2. Add x more elements of bytes ahead of current position, where x is the Byte Width (max number of hex digits in logical table) * 3. Check if this byte sequence is in the control code/table switch/end token lists for this logical table * 4. If not, check if this byte sequence is in the dictionary * 5. If not, go back to 1 with using Byte Width - 1 * 6. When back down to the original single byte, if it is still not found in the lists of the dict, it is not in the table */ // increase testloop by the ByteWidth // ensure that the length of the testseq does not go past the upper bound of _in testloop = thisframe.Table.ByteWidth > remaining ? remaining : thisframe.Table.ByteWidth; // Loop for test byte sequence for (; testloop > 0; testloop--) { // make the testseq as long as testloop and copy that many bytes from _in @ current position (i) testseq = new byte[testloop]; Buffer.BlockCopy(Data, outerloop, testseq, 0, testloop); // check to see if this test sequence matches the previous table switch sequence, if the match mode is -1 if (thisframe.MatchCount == -1 && thisframe.OrigSeq.SequenceEqual <byte>(testseq)) { // then fall back to the previous logical table (match frame) thisframe = TableStack.Pop(); outerloop++; break; } // check each of the dictionaries for the test bytes // table switch if (thisframe.Table.TableSwitches.ContainsKey(testseq)) { // cache the variable for speed var thisswitch = thisframe.Table.TableSwitches[testseq]; TableStack.Push(thisframe); thisframe = new MatchFrame(Table.LogicalTables[thisswitch.TableID], thisswitch.Matches); if (thisframe.MatchCount == -1) { thisframe.OrigSeq = testseq; } if (thisframe.MatchCount > 0) { thisframe.MatchByte = testseq[0]; } outerloop += testloop; break; } // control code if (thisframe.Table.ControlCodes.ContainsKey(testseq)) { // NOTE! It is calling the byte comparer EVERY TIME ControlCodes[testseq] is caleld. cache the variable?? // cached variable for speed var thiscode = thisframe.Table.ControlCodes[testseq]; if (thiscode.Params == null) { // this control code has no paramaters, so use quick and easy formatting matched = true; _out.Append('[' + thiscode.Label + ']'); _out.Append(thiscode.Formatting); outerloop += testloop; break; } else { matched = true; int paramoffset = outerloop + testloop; int paramcount = 0; _out.Append('[' + thiscode.Label); foreach (LogicalTable.ControlCode.Parameter thiscodeparam in thiscode.Params) { switch (thiscodeparam.Type) { case LogicalTable.ControlCode.Parameter.NumberType.Hex: _out.Append(' ' + thiscodeparam.Label + "=0x" + Data[paramoffset + paramcount].ToString("X")); break; case LogicalTable.ControlCode.Parameter.NumberType.Decimal: _out.Append(' ' + thiscodeparam.Label + '=' + Data[paramoffset + paramcount].ToString()); break; case LogicalTable.ControlCode.Parameter.NumberType.Binary: _out.Append(' ' + thiscodeparam.Label + '=' + Convert.ToString(Data[paramoffset + paramcount], 2)); break; } paramcount++; } _out.Append(']'); _out.Append(thiscode.Formatting); outerloop += (testloop + paramcount); break; } } // end token if (thisframe.Table.EndTokens.ContainsKey(testseq)) { // cached variable var thistoken = thisframe.Table.EndTokens[testseq]; matched = true; _out.Append("[" + thistoken.Label + "]"); _out.Append(thistoken.Formatting); if (ShowAddr) { _out.AppendLine("[0x" + (StartOffset + outerloop + 1).ToString("X") + "]"); } outerloop += testloop; break; } // not found among any of the non-standard entries so check standard if (thisframe.Table.StdDict.ContainsKey(testseq)) { matched = true; _out.Append(thisframe.Table.StdDict[testseq]); outerloop += testloop; break; } // if we are down to the last iteration (original byte) and still haven't found anything, the byte isn't found if (testloop == 1) { matched = false; if (TableStack.Count > 0 && thisframe.MatchCount == 0) { thisframe = TableStack.Pop(); } else { _out.Append("[" + testseq[0].ToString("X2") + "]"); outerloop++; } } } // end of test loop // // if there are match frames on the table stack, let's check for a match and act accordingly if (TableStack.Count > 0) { // matching mode is positive value [with value at 1, the minimum] and there was a match // then return to the previous logical table (matchframe) if (thisframe.MatchCount == 1 && matched) { thisframe = TableStack.Pop(); } // else if matching mode is positive value [with value greater than 1] and there was a match // then decrease the value by 1 else if (thisframe.MatchCount > 1 && matched) { thisframe.Decrease(); } } // didn't find nuthin'! } return(_out.ToString()); }