-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathutypes.pas
153 lines (120 loc) · 3.79 KB
/
utypes.pas
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
unit utypes;
{$mode objfpc}
interface
uses Classes, SysUtils, ulist;
type
// Lexer Types
TToken = class(TObject)
id: Byte;
s: AnsiString;
line: Integer;
end;
// Parser / Syntax Tree Types
TASTTreeNode = class(TObject)
operation: Byte;
s: AnsiString; // all strings like identifier, constants etc
n: Extended; // numbers (used internally to prevent conversions string->number)
var_id: Integer; // assigns a unique index to every variable for example a becomes vars[0], b becomes vars[1] etc.
line: Integer; // original line in source
children: TLightList;
constructor Create(param_operation: Byte; param_s: AnsiString; param_line: Integer);
function getChild(index: Integer): TASTTreeNode;
function firstChild: TASTTreeNode;
function secondChild: TASTTreeNode;
function thirdChild: TASTTreeNode;
function fourthChild: TASTTreeNode;
function lastChild: TASTTreeNode;
procedure debug(symbol_table: TStringList; messages: TStringList; current_depth: integer = 0);
procedure clearChildren;
destructor Destroy; override;
end;
implementation
uses uconstants, uutils;
constructor TASTTreeNode.Create(param_operation: Byte; param_s: AnsiString; param_line: Integer);
begin
operation := param_operation;
s := param_s;
n := 0;
// try to automatically populate number field for caching
if param_operation = CopNumber then
begin
if pos('$', s) > 0 then // check for hex numbers
n := StrToInt(s)
else
n := StrToFloatDef(s, 0, FormatSettings);
end;
var_id := 0; // Default is function result
line := param_line;
children := TLightList.Create;
end;
function TASTTreeNode.getChild(index: Integer): TASTTreeNode;
begin
Result := TASTTreeNode(children.Items(index));
end;
// for convenience...
function TASTTreeNode.firstChild: TASTTreeNode;
begin
Result := TASTTreeNode(children.GetFirst);
end;
function TASTTreeNode.secondChild: TASTTreeNode;
begin
Result := TASTTreeNode(children.GetSecond);
end;
function TASTTreeNode.thirdChild: TASTTreeNode;
begin
Result := TASTTreeNode(children.GetThird);
end;
function TASTTreeNode.fourthChild: TASTTreeNode;
begin
Result := TASTTreeNode(children.GetFourth);
end;
function TASTTreeNode.lastChild: TASTTreeNode;
begin
Result := TASTTreeNode(children.Get);
end;
// "pretty print" the syntax tree for debug output
procedure TASTTreeNode.debug(symbol_table: TStringList; messages: TStringList; current_depth: integer = 0);
var i: Integer;
temp_s: AnsiString;
begin
temp_s := '';
for i := 1 to current_depth do temp_s := temp_s + (' '); // indentation
if children.Count > 0 then
temp_s := temp_s + ('+ ')
else
temp_s := temp_s + ('| ');
temp_s := temp_s + operationtostr(operation);
if (operation = CopVariable) then
temp_s := temp_s + ' ' + symbol_table.Strings[var_id] + ', id: ' + IntToStr(var_id);
if s <> '' then
begin
if operation = CopString then
temp_s := temp_s + ' ''' + s + ''''
else
temp_s := temp_s + ' ' + s; // number etc
end;
messages.Add(temp_s);
for i := 0 to children.Count - 1 do getChild(i).debug(symbol_table, messages, current_depth + 1);
dec(current_depth);
end;
procedure TASTTreeNode.clearChildren;
var node: TASTTreeNode;
begin
while children.Count > 0 do
begin
node := TASTTreeNode(children.RemoveFirst);
FreeAndNil(node);
end;
end;
// deleting the master node will delete the whole tree
destructor TASTTreeNode.Destroy;
begin
clearChildren;
FreeAndNil(children);
inherited;
end;
begin
// needed to convert floats correctly
FormatSettings.ThousandSeparator := ',';
FormatSettings.DecimalSeparator := '.';
end.