static IParser <byte, InstructionParseState, InstructionParseState> ParseStringLiteral() { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null) { return null; } var results = input.Result; var peFile = results.MethodDefinition.Module.PEFile; var size = (int)StreamID.UserStrings.IndexSize(peFile); if (input.RemainingInput.Count < size) { return null; } uint index; if (size == 2) { index = input.RemainingInput.ReadLittleEndianUShort(); } else { index = input.RemainingInput.ReadLittleEndianUInt(); } var operand = peFile.ReadUserString(index); results.Operand = operand; results.PrettyPrint = results.PrettyPrint.Then(b => b.AppendFormat(" {0}", operand.Escape())); return ParseState.Create(input.ConsumedInput.Expand(size), input.RemainingInput.SubList(size), results); }, (byte)0 )); }
static IParser <byte, InstructionParseState, InstructionParseState> ParseFixedSizeOperand <T>( Func <IParseState <byte, InstructionParseState>, T> f, int bytesNeeded, Action <T, StringBuilder> prettyPrint, Func <T, bool> predicate ) { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null || input.RemainingInput.Count < bytesNeeded) { return null; } var result = input.Result; var operand = f(input); if (!predicate(operand)) { return null; } result.Operand = operand; result.PrettyPrint = result.PrettyPrint.Then(b => prettyPrint(operand, b)); return ParseState.Create(input.ConsumedInput.Expand(bytesNeeded), input.RemainingInput.SubList(bytesNeeded), result); }, (byte)0 )); }
static IParser <byte, InstructionParseState, InstructionParseState> ParseSwitchTable() { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null || input.RemainingInput.Count < 4) { return null; } var n = checked ((int)input.RemainingInput.ReadLittleEndianUInt()); if (input.RemainingInput.Count < checked ((n + 1) * 4)) { return null; } var results = input.Result; var operand = GetSwitchTargets(input, n); results.Operand = operand; var targets = Enumerable.Range(1, n).Select(x => input.RemainingInput.SubList(x * 4).ReadLittleEndianInt()); results.PrettyPrint.Then(b => targets.Print(b, ",", " ", "")); return ParseState.Create( input.ConsumedInput.Expand((n + 1) * 4), input.RemainingInput.SubList((n + 1) * 4), results ); }, (byte)0 )); }
static IParser <byte, InstructionParseState, InstructionParseState> Consume(byte b) { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null || input.RemainingInput.Count == 0 || input.RemainingInput[0] != b) { return null; } return ParseState.Create(input.ConsumedInput.Expand(1), input.RemainingInput.SubList(1), input.Result); }, b )); }
static IParser <byte, InstructionParseState, InstructionParseState> SetOperand(Object operand) { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null) { return null; } var result = input.Result; result.Operand = operand; return ParseState.Create(input.ConsumedInput, input.RemainingInput, result); }, (byte)0 )); }
static IParser <byte, InstructionParseState, InstructionParseState> SetOpcode(Opcode opcode, String pretty) { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { if (input == null) { return null; } var result = input.Result; result.Opcode = opcode; result.PrettyPrint = builder => builder.Append(pretty); return ParseState.Create(input.ConsumedInput, input.RemainingInput, result); }, (byte)0 )); }
static IParser <byte, InstructionParseState, InstructionParseState> ParseNestedInstruction() { return(FunctionalParser.Create( (IParseState <byte, InstructionParseState> input) => { var output = s_parser.Parse(input); if (output == null) { return null; } var result = input.AssumeNotNull().Result; result.NestedInstruction = output.Result; result.PrettyPrint = result.PrettyPrint.Then(b => b.Append(" ")).Then( b => output.Result.ToString(b) ); return ParseState.Create(output.ConsumedInput, output.RemainingInput, result); }, (byte)0 )); }
static IParser <byte, InstructionParseState, Instruction> Grammar( params IParser <byte, InstructionParseState, InstructionParseState>[] parsers ) { var tableParser = CreateTableParser(parsers); return(new FunctionalParser <byte, InstructionParseState, Instruction>( startState => { var endState = tableParser.Parse(startState); if (endState == null) { return null; } return ParseState.Create( endState.ConsumedInput, endState.RemainingInput, CreateInstruction(endState) ); }, tableParser.LookAhead )); }
public static SortedDictionary <int, Instruction> Parse(IReadOnlyList <byte> buffer, MethodDefinition method) { var state = ParseState.Create(buffer.SubList(0, 0), buffer.SubList(0), new InstructionParseState(0, method)); var ret = new SortedDictionary <int, Instruction>(); while (state.RemainingInput.Count > 0) { var output = s_parser.Parse(state); if (output == null) { throw new InvalidOperationException("Unexpected failure when parsing instruction."); } ret.Add(state.Result.InstructionContext.Offset, output.Result); state = ParseState.Create( output.RemainingInput.SubList(0, 0), output.RemainingInput, new InstructionParseState( state.Result.InstructionContext.Offset + output.ConsumedInput.Count, method ) ); } return(ret); }