forked from ReClassNET/ReClass.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTokenReader.cs
More file actions
131 lines (114 loc) · 3.46 KB
/
Copy pathTokenReader.cs
File metadata and controls
131 lines (114 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Design taken from https://github.com/pieterderycke/Jace
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Linq;
namespace ReClassNET.AddressParser
{
class TokenReader
{
/// <summary>
/// Read in the provided formula and convert it into a list of takens that can be processed by the
/// Abstract Syntax Tree Builder.
/// </summary>
/// <param name="formula">The formula that must be converted into a list of tokens.</param>
/// <returns>The list of tokens for the provided formula.</returns>
public List<Token> Read(string formula)
{
Contract.Requires(formula != null);
var tokens = new List<Token>();
var isFormulaSubPart = true;
var characters = formula.ToCharArray();
for (var i = 0; i < characters.Length; ++i)
{
if (characters[i] == '<')
{
var buffer = string.Empty;
while (++i < characters.Length && IsPartOfModuleName(characters[i]))
{
buffer += characters[i];
}
if (i >= characters.Length)
{
throw new ParseException("Unexpected end of input detected.");
}
if (characters[i] != '>')
{
throw new ParseException($"Invalid token '{characters[i]}' detected at position {i}.");
}
++i;
tokens.Add(new Token { TokenType = TokenType.ModuleOffset, Value = buffer });
isFormulaSubPart = false;
if (i == characters.Length)
{
continue;
}
}
if (IsPartOfNumeric(characters[i], true, isFormulaSubPart))
{
var buffer = characters[i].ToString();
while (++i < characters.Length && IsPartOfNumeric(characters[i], false, isFormulaSubPart))
{
buffer += characters[i];
}
if (buffer.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
buffer = buffer.Substring(2);
}
long offsetValue;
if (long.TryParse(buffer, NumberStyles.HexNumber, null, out offsetValue))
{
#if WIN64
var address = (IntPtr)offsetValue;
#else
var address = (IntPtr)unchecked((int)offsetValue);
#endif
tokens.Add(new Token { TokenType = TokenType.Offset, Value = address });
isFormulaSubPart = false;
}
else
{
throw new ParseException($"'{buffer}' is not a valid number.");
}
if (i == characters.Length)
{
continue;
}
}
switch (characters[i])
{
case ' ':
continue;
case '+':
case '-':
case '*':
case '/':
tokens.Add(new Token { TokenType = TokenType.Operation, Value = characters[i] });
isFormulaSubPart = true;
break;
case '[':
tokens.Add(new Token { TokenType = TokenType.LeftBracket, Value = characters[i] });
isFormulaSubPart = true;
break;
case ']':
tokens.Add(new Token { TokenType = TokenType.RightBracket, Value = characters[i] });
isFormulaSubPart = false;
break;
default:
throw new ParseException($"Invalid token '{characters[i]}' detected at position {i}.");
}
}
return tokens;
}
private bool IsPartOfNumeric(char character, bool isFirstCharacter, bool isFormulaSubPart)
{
return (character >= '0' && character <= '9') || (character >= 'a' && character <= 'f') || (character >= 'A' && character <= 'F') || (isFormulaSubPart && !isFirstCharacter && (character == 'x' || character == 'X'));
}
private bool IsPartOfModuleName(char character)
{
return !Path.GetInvalidFileNameChars().Contains(character);
}
}
}