1 {(*}
2 (*------------------------------------------------------------------------------
3  Delphi Code formatter source code
4 
5 The Original Code is Token.pas, released April 2000.
6 The Initial Developer of the Original Code is Anthony Steele.
7 Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
8 All Rights Reserved.
9 Contributor(s): Anthony Steele.
10 
11 The contents of this file are subject to the Mozilla Public License Version 1.1
12 (the "License"). you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at http://www.mozilla.org/NPL/
14 
15 Software distributed under the License is distributed on an "AS IS" basis,
16 WITHOUT WARRANTY OF ANY KIND, either express or implied.
17 See the License for the specific language governing rights and limitations
18 under the License.
19 
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 or later (the "GPL")
22 See http://www.gnu.org/licenses/gpl.html
23 ------------------------------------------------------------------------------*)
24 {*)}
25 
26 unit SourceToken;
27 
28 { Created AFS 29 Nov 1999
29   Token  - element of source code text }
30 
31 {$I JcfGlobal.inc}
32 
33 interface
34 
35 uses
36   SysUtils,
37   { local }
38   Tokens, ParseTreeNode;
39 
40 type
41 
42   TSourceToken = class(TParseTreeNode)
43   private
44     { property implementation }
45     fsSourceCode: String;
46     feTokenType: TTokenType;
47     feWordType: TWordType;
48     feCommentStyle: TCommentStyle;
49 
50     fsFileName: string;
51     fiXPosition, fiYPosition: integer;
52     fiSolidTokenOnLineIndex: integer;
53     fbPreprocessedOut: boolean;
54 
55     fePreprocessorSymbol: TPreProcessorSymbolType;
56     fsPreProcessorText: String;
57 
58   protected
59   public
60     constructor Create;
61 
Describenull62     function Describe: string; override;
DescribePositionnull63     function DescribePosition: string;
64 
IsSolidnull65     function IsSolid: boolean;
SourceLinenull66     function SourceLine: string;
67 
HasChildNodenull68     function HasChildNode(const peTokens: TTokenTypeSet): boolean; override;
HasChildNodenull69     function HasChildNode(const peTokens: TTokenTypeSet;
70       const {%H-}piMaxDepth: integer): boolean; override;
71 
SolidChildCountnull72     function SolidChildCount: integer; override;
FirstSolidLeafnull73     function FirstSolidLeaf: TParseTreeNode; override;
IsLeafnull74     function IsLeaf: boolean; override;
75 
76     { navigating the source tree as if it was a list }
NextTokennull77     function NextToken: TSourceToken;
PriorTokennull78     function PriorToken: TSourceToken;
NextSolidTokennull79     function NextSolidToken: TSourceToken;
PriorSolidTokennull80     function PriorSolidToken: TSourceToken;
NextTokenWithExclusionsnull81     function NextTokenWithExclusions(const peExclusions: TTokenTypeSet): TSourceToken;
PriorTokenWithExclusionsnull82     function PriorTokenWithExclusions(const peExclusions: TTokenTypeSet): TSourceToken;
83 
84     procedure GeneratePreProcessorData;
85 
86     property TokenType: TTokenType Read feTokenType Write feTokenType;
87     property WordType: TWordType Read feWordType Write feWordType;
88 
89     property SourceCode: String Read fsSourceCode Write fsSourceCode;
90     property CommentStyle: TCommentStyle Read feCommentStyle Write feCommentStyle;
91 
92     property FileName: string read fsFileName write fsFileName;
93     property XPosition: integer Read fiXPosition Write fiXPosition;
94     property YPosition: integer Read fiYPosition Write fiYPosition;
95     property SolidTokenOnLineIndex: integer
96       Read fiSolidTokenOnLineIndex Write fiSolidTokenOnLineIndex;
97 
98     property PreprocessorSymbol: TPreProcessorSymbolType Read fePreprocessorSymbol;
99     property PreProcessorText: String Read fsPreProcessorText;
100 
101     property PreprocessedOut: boolean Read fbPreprocessedOut Write fbPreprocessedOut;
102   end;
103 
104   TSourceTokenProcedure = procedure(const pt: TSourceToken) of object;
105 
106 implementation
107 
108 {-------------------------------------------------------------------------------
109  TSourceToken }
110 
111 constructor TSourceToken.Create;
112 begin
113   inherited;
114 
115   feTokenType  := ttUnknown;
116   fsSourceCode := '';
117 
118   feWordType     := wtNotAWord;
119   feCommentStyle := eNotAComment;
120 
121   fiXPosition := -1;
122   fiYPosition := -1;
123   fiSolidTokenOnLineIndex := -1;
124 
125   fePreprocessorSymbol := ppNone;
126   fsPreProcessorText   := '';
127   fbPreprocessedOut    := False;
128 end;
129 
Describenull130 function TSourceToken.Describe: string;
131 const
132   StructuredTokens: TTokenTypeSet =
133     [ttComment, ttNumber, ttQuotedLiteralString, ttUnknown, ttPunctuation, ttIdentifier];
134 begin
135   if TokenType = ttIdentifier then
136     Result := SourceCode
137   else
138   begin
139     Result := TokenTypeToString(TokenType);
140     if (TokenType in StructuredTokens) then
141       Result := Result + ' ' + SourceCode;
142   end;
143 end;
144 
TSourceToken.DescribePositionnull145 function TSourceToken.DescribePosition: string;
146 begin
147   Result := '';
148 
149   if YPosition > 0 then
150   begin
151     Result := Result + 'on line ' + IntToStr(YPosition);
152 
153     if XPosition > 0 then
154       Result := Result + ' position ' + IntToStr(XPosition);
155   end;
156 end;
157 
TSourceToken.HasChildNodenull158 function TSourceToken.HasChildNode(const peTokens: TTokenTypeSet): boolean;
159 begin
160   Result := (TokenType in peTokens);
161 end;
162 
TSourceToken.HasChildNodenull163 function TSourceToken.HasChildNode(const peTokens: TTokenTypeSet;
164   const piMaxDepth: integer): boolean;
165 begin
166   Result := (TokenType in peTokens);
167 end;
168 
IsSolidnull169 function TSourceToken.IsSolid: boolean;
170 begin
171   Result := not (TokenType in NotSolidTokens);
172 end;
173 
174 
NextTokennull175 function TSourceToken.NextToken: TSourceToken;
176 var
177   lcTemp: TParseTreeNode;
178 begin
179   Result := nil;
180   lcTemp := NextLeafNode;
181   if lcTemp = nil then
182     exit;
183 
184   Assert(lcTemp is TSourceToken, 'Next leaf is not token at ' + Describe);
185   Result := TSourceToken(lcTemp);
186 end;
187 
TSourceToken.PriorTokennull188 function TSourceToken.PriorToken: TSourceToken;
189 var
190   lcTemp: TParseTreeNode;
191 begin
192   Result := nil;
193   lcTemp := PriorLeafNode;
194   if lcTemp = nil then
195     exit;
196 
197   Assert(lcTemp is TSourceToken, 'prior leaf is not token at ' + Describe);
198   Result := TSourceToken(lcTemp);
199 end;
200 
TSourceToken.NextSolidTokennull201 function TSourceToken.NextSolidToken: TSourceToken;
202 begin
203   Result := NextToken;
204 
205   while (Result <> nil) and ( not Result.IsSolid) do
206     Result := Result.NextToken;
207 end;
208 
NextTokenWithExclusionsnull209 function TSourceToken.NextTokenWithExclusions(
210   const peExclusions: TTokenTypeSet): TSourceToken;
211 begin
212   Result := NextToken;
213 
214   while (Result <> nil) and (Result.TokenType in peExclusions) do
215     Result := Result.NextToken;
216 end;
217 
TSourceToken.PriorTokenWithExclusionsnull218 function TSourceToken.PriorTokenWithExclusions(
219   const peExclusions: TTokenTypeSet): TSourceToken;
220 begin
221   Result := PriorToken;
222 
223   while (Result <> nil) and (Result.TokenType in peExclusions) do
224     Result := Result.PriorToken;
225 end;
226 
227 
TSourceToken.PriorSolidTokennull228 function TSourceToken.PriorSolidToken: TSourceToken;
229 begin
230   Result := PriorToken;
231 
232   while (Result <> nil) and ( not Result.IsSolid) do
233     Result := Result.PriorToken;
234 end;
235 
SolidChildCountnull236 function TSourceToken.SolidChildCount: integer;
237 begin
238   if IsSolid then
239     Result := 1
240   else
241     Result := 0;
242 end;
243 
SourceLinenull244 function TSourceToken.SourceLine: string;
245 var
246   lcLineToken: TSourceToken;
247 begin
248   // find the return at the start of the line
249   // or nil for start of first line
250   lcLineToken := self;
251 
252   while lcLineToken.PriorToken <> nil do
253   begin
254     if lcLineToken.PriorToken.TokenType = ttReturn then
255       break
256     else
257       lcLineToken := lcLineToken.PriorToken;
258   end;
259 
260   // walk to the end of the line
261   Result := '';
262   while (lcLineToken <> nil) and (lcLineToken.TokenType <> ttReturn) do
263   begin
264     Result := Result + lcLineToken.SourceCode;
265     lcLineToken := lcLineToken.NextToken;
266   end;
267 end;
268 
TSourceToken.FirstSolidLeafnull269 function TSourceToken.FirstSolidLeaf: TParseTreeNode;
270 begin
271   if IsSolid then
272     Result := self
273   else
274     Result := nil;
275 end;
276 
IsLeafnull277 function TSourceToken.IsLeaf: boolean;
278 begin
279   Result := True;
280 end;
281 
282 procedure TSourceToken.GeneratePreProcessorData;
283 begin
284   GetPreprocessorSymbolData(SourceCode, fePreprocessorSymbol, fsPreProcessorText);
285 end;
286 
287 end.
288