| 1 | //  HRParser v1.0.1 (25.Sep.2000) | 
|---|
| 2 | //  Simple and fast parser classes. | 
|---|
| 3 | //  by Colin A Ridgewell | 
|---|
| 4 | // | 
|---|
| 5 | //  Copyright (C) 1999,2000 Hayden-R Ltd | 
|---|
| 6 | //  http://www.haydenr.com | 
|---|
| 7 | // | 
|---|
| 8 | //  This program is free software; you can redistribute it and/or modify it | 
|---|
| 9 | //  under the terms of the GNU General Public License as published by the | 
|---|
| 10 | //  Free Software Foundation; either version 2 of the License, or (at your | 
|---|
| 11 | //  option) any later version. | 
|---|
| 12 | // | 
|---|
| 13 | //  This program is distributed in the hope that it will be useful, but | 
|---|
| 14 | //  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | 
|---|
| 15 | //  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 
|---|
| 16 | //  more details. | 
|---|
| 17 | // | 
|---|
| 18 | //  You should have received a copy of the GNU General Public License along | 
|---|
| 19 | //  with this program (gnu_license.htm); if not, write to the | 
|---|
| 20 | // | 
|---|
| 21 | //  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|---|
| 22 | // | 
|---|
| 23 | //  To contact us via e-mail use the following addresses... | 
|---|
| 24 | // | 
|---|
| 25 | //  bug@haydenr.u-net.com       - to report a bug | 
|---|
| 26 | //  support@haydenr.u-net.com   - for general support | 
|---|
| 27 | //  wishlist@haydenr.u-net.com  - add new requirement to wish list | 
|---|
| 28 | // | 
|---|
| 29 | unit HRParser; | 
|---|
| 30 |  | 
|---|
| 31 | interface | 
|---|
| 32 |  | 
|---|
| 33 | uses | 
|---|
| 34 | Classes, SysUtils, HRBuffers; | 
|---|
| 35 |  | 
|---|
| 36 | type | 
|---|
| 37 | THRTokenType = Byte; | 
|---|
| 38 |  | 
|---|
| 39 | const | 
|---|
| 40 | HR_PARSER_STREAM_BUFFER_SIZE = 2048; {bytes} | 
|---|
| 41 | HR_PARSER_TOKEN_BUFFER_SIZE = 1024; {bytes} | 
|---|
| 42 |  | 
|---|
| 43 | {THRParser tokens} | 
|---|
| 44 | HR_TOKEN_NIL = 0; | 
|---|
| 45 | HR_TOKEN_EOF = 1; | 
|---|
| 46 | HR_TOKEN_CHAR = 2; | 
|---|
| 47 |  | 
|---|
| 48 | {THRParserText tokens} | 
|---|
| 49 | HR_TOKEN_TEXT_SPACE = 3; | 
|---|
| 50 | HR_TOKEN_TEXT_SYMBOL = 4; | 
|---|
| 51 | HR_TOKEN_TEXT_INTEGER = 5; | 
|---|
| 52 | HR_TOKEN_TEXT_FLOAT = 6; | 
|---|
| 53 |  | 
|---|
| 54 | type | 
|---|
| 55 | THRToken = record | 
|---|
| 56 | Token: PChar; | 
|---|
| 57 | TokenType: THRTokenType; | 
|---|
| 58 | SourcePos: Longint; | 
|---|
| 59 | Line: Longint; | 
|---|
| 60 | LinePos: Integer; | 
|---|
| 61 | end; | 
|---|
| 62 |  | 
|---|
| 63 | THRParser = class( TObject ) | 
|---|
| 64 | private | 
|---|
| 65 | function GetSource: TStream; | 
|---|
| 66 | procedure SetSource(Value: TStream); | 
|---|
| 67 | procedure SetSourcePos(Value: LongInt); | 
|---|
| 68 | protected | 
|---|
| 69 | FSourceBuf: THRBufferStream; | 
|---|
| 70 | FSourcePos: LongInt; | 
|---|
| 71 | FLine: Longint; | 
|---|
| 72 | FLineStartSourcePos: Longint; | 
|---|
| 73 | FTokenBuf: THRBufferChar; | 
|---|
| 74 | FToken: THRToken; | 
|---|
| 75 | procedure IncLine; | 
|---|
| 76 | procedure SkipToSourcePos(const Pos: Longint); | 
|---|
| 77 | procedure SkipBlanks; | 
|---|
| 78 | procedure GetNextToken; virtual; | 
|---|
| 79 | public | 
|---|
| 80 | constructor Create; virtual; | 
|---|
| 81 | destructor Destroy; override; | 
|---|
| 82 | property Source: TStream read GetSource write SetSource; | 
|---|
| 83 | property SourcePos: Longint read FSourcePos write SetSourcePos; | 
|---|
| 84 | property Token: THRToken read FToken; | 
|---|
| 85 | function NextToken: THRToken; | 
|---|
| 86 | end; | 
|---|
| 87 |  | 
|---|
| 88 | THRParserText = class( THRParser ) | 
|---|
| 89 | private | 
|---|
| 90 | protected | 
|---|
| 91 | procedure GetNextToken; override; | 
|---|
| 92 | public | 
|---|
| 93 | constructor Create; override; | 
|---|
| 94 | destructor Destroy; override; | 
|---|
| 95 | end; | 
|---|
| 96 |  | 
|---|
| 97 | implementation | 
|---|
| 98 |  | 
|---|
| 99 |  | 
|---|
| 100 | { T H R P a r s e r } | 
|---|
| 101 |  | 
|---|
| 102 | constructor THRParser.Create; | 
|---|
| 103 | begin | 
|---|
| 104 | FSourceBuf := THRBufferStream.Create; | 
|---|
| 105 | FSourceBuf.Size := HR_PARSER_STREAM_BUFFER_SIZE; | 
|---|
| 106 | FTokenBuf := THRBufferChar.Create; | 
|---|
| 107 | FTokenBuf.Size := HR_PARSER_TOKEN_BUFFER_SIZE; | 
|---|
| 108 | FSourcePos := 0; | 
|---|
| 109 | end; | 
|---|
| 110 |  | 
|---|
| 111 |  | 
|---|
| 112 | destructor THRParser.Destroy; | 
|---|
| 113 | begin | 
|---|
| 114 | FTokenBuf.Free; | 
|---|
| 115 | FTokenBuf := nil; | 
|---|
| 116 | FSourceBuf.Free; | 
|---|
| 117 | FSourceBuf := nil; | 
|---|
| 118 | inherited Destroy; | 
|---|
| 119 | end; | 
|---|
| 120 |  | 
|---|
| 121 |  | 
|---|
| 122 | function THRParser.GetSource: TStream; | 
|---|
| 123 | begin | 
|---|
| 124 | Result := FSourceBuf.Stream; | 
|---|
| 125 | end; | 
|---|
| 126 |  | 
|---|
| 127 |  | 
|---|
| 128 | procedure THRParser.SetSource(Value: TStream); | 
|---|
| 129 | begin | 
|---|
| 130 | FSourceBuf.Stream := Value; | 
|---|
| 131 | end; | 
|---|
| 132 |  | 
|---|
| 133 |  | 
|---|
| 134 | procedure THRParser.SetSourcePos(Value: LongInt); | 
|---|
| 135 | begin | 
|---|
| 136 | SkipToSourcePos( Value ); | 
|---|
| 137 | end; | 
|---|
| 138 |  | 
|---|
| 139 |  | 
|---|
| 140 | procedure THRParser.IncLine; | 
|---|
| 141 | begin | 
|---|
| 142 | Inc( FLine ); | 
|---|
| 143 | FLineStartSourcePos := FSourcePos; | 
|---|
| 144 | end; | 
|---|
| 145 |  | 
|---|
| 146 |  | 
|---|
| 147 | procedure THRParser.SkipToSourcePos(const Pos: Longint); | 
|---|
| 148 | begin | 
|---|
| 149 | FSourcePos := 0; | 
|---|
| 150 | FLine := 0; | 
|---|
| 151 | FLineStartSourcePos := 0; | 
|---|
| 152 | FSourceBuf[ FSourcePos ]; | 
|---|
| 153 | while not FSourceBuf.EOB and ( FSourcePos < Pos ) do | 
|---|
| 154 | begin | 
|---|
| 155 | if FSourceBuf[ FSourcePos ] = #10 then IncLine; | 
|---|
| 156 | Inc( FSourcePos ); | 
|---|
| 157 | FSourceBuf[ FSourcePos ]; | 
|---|
| 158 | end; | 
|---|
| 159 | end; | 
|---|
| 160 |  | 
|---|
| 161 |  | 
|---|
| 162 | procedure THRParser.SkipBlanks; | 
|---|
| 163 | begin | 
|---|
| 164 | FSourceBuf[ FSourcePos ]; | 
|---|
| 165 | while not FSourceBuf.EOB do | 
|---|
| 166 | begin | 
|---|
| 167 | case FSourceBuf[ FSourcePos ] of | 
|---|
| 168 | #32..#255 : Exit; | 
|---|
| 169 | #10 : IncLine; | 
|---|
| 170 | end; | 
|---|
| 171 | Inc( FSourcePos ); | 
|---|
| 172 | FSourceBuf[ FSourcePos ]; | 
|---|
| 173 | end; | 
|---|
| 174 | end; | 
|---|
| 175 |  | 
|---|
| 176 |  | 
|---|
| 177 | procedure THRParser.GetNextToken; | 
|---|
| 178 | begin | 
|---|
| 179 | FSourceBuf[ FSourcePos ]; | 
|---|
| 180 | if not FSourceBuf.EOB then | 
|---|
| 181 | begin | 
|---|
| 182 | {single char} | 
|---|
| 183 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 184 | Inc( FSourcePos ); | 
|---|
| 185 | FToken.TokenType := HR_TOKEN_CHAR; | 
|---|
| 186 | end | 
|---|
| 187 | else | 
|---|
| 188 | begin | 
|---|
| 189 | {end of buffer} | 
|---|
| 190 | FToken.TokenType := HR_TOKEN_EOF; | 
|---|
| 191 | end; | 
|---|
| 192 | end; | 
|---|
| 193 |  | 
|---|
| 194 |  | 
|---|
| 195 |  | 
|---|
| 196 | function THRParser.NextToken: THRToken; | 
|---|
| 197 | begin | 
|---|
| 198 | FTokenBuf.Position := 0; | 
|---|
| 199 |  | 
|---|
| 200 | SkipBlanks; | 
|---|
| 201 |  | 
|---|
| 202 | {store start pos of token} | 
|---|
| 203 | with FToken do | 
|---|
| 204 | begin | 
|---|
| 205 | SourcePos := FSourcePos; | 
|---|
| 206 | Line := FLine; | 
|---|
| 207 | LinePos := FSourcePos - FLineStartSourcePos; | 
|---|
| 208 | end; | 
|---|
| 209 |  | 
|---|
| 210 | GetNextToken; | 
|---|
| 211 |  | 
|---|
| 212 | FTokenBuf.Write( #0 ); {null terminate.} | 
|---|
| 213 | FToken.Token := FTokenBuf.Buffer; | 
|---|
| 214 | Result := FToken; | 
|---|
| 215 | end; | 
|---|
| 216 |  | 
|---|
| 217 |  | 
|---|
| 218 | { T H R P a r s e r T e x t } | 
|---|
| 219 |  | 
|---|
| 220 | constructor THRParserText.Create; | 
|---|
| 221 | begin | 
|---|
| 222 | inherited Create; | 
|---|
| 223 | end; | 
|---|
| 224 |  | 
|---|
| 225 |  | 
|---|
| 226 | destructor THRParserText.Destroy; | 
|---|
| 227 | begin | 
|---|
| 228 | inherited Destroy; | 
|---|
| 229 | end; | 
|---|
| 230 |  | 
|---|
| 231 |  | 
|---|
| 232 | procedure THRParserText.GetNextToken; | 
|---|
| 233 | begin | 
|---|
| 234 | repeat | 
|---|
| 235 |  | 
|---|
| 236 | {spaces} | 
|---|
| 237 | if FSourceBuf[ FSourcePos ] = ' ' then | 
|---|
| 238 | begin | 
|---|
| 239 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 240 | Inc( FSourcePos ); | 
|---|
| 241 | while FSourceBuf[ FSourcePos ] = ' ' do | 
|---|
| 242 | begin | 
|---|
| 243 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 244 | Inc( FSourcePos ); | 
|---|
| 245 | end; | 
|---|
| 246 | FToken.TokenType := HR_TOKEN_TEXT_SPACE; | 
|---|
| 247 | Break;{out of repeat} | 
|---|
| 248 | end; | 
|---|
| 249 |  | 
|---|
| 250 | {symbols} | 
|---|
| 251 | if FSourceBuf[ FSourcePos ] in [ 'A'..'Z', 'a'..'z', '_' ] then | 
|---|
| 252 | begin | 
|---|
| 253 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 254 | Inc( FSourcePos ); | 
|---|
| 255 | while True do | 
|---|
| 256 | begin | 
|---|
| 257 | case FSourceBuf[ FSourcePos ] of | 
|---|
| 258 |  | 
|---|
| 259 | 'A'..'Z', 'a'..'z', '0'..'9', '_' : | 
|---|
| 260 | begin | 
|---|
| 261 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 262 | Inc( FSourcePos ); | 
|---|
| 263 | end; | 
|---|
| 264 |  | 
|---|
| 265 | '''' : | 
|---|
| 266 | begin{apostrophies} | 
|---|
| 267 | if FSourceBuf[ FSourcePos + 1 ] in [ 'A'..'Z', 'a'..'z', '0'..'9', '_' ] then | 
|---|
| 268 | begin | 
|---|
| 269 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 270 | Inc( FSourcePos ); | 
|---|
| 271 | end | 
|---|
| 272 | else | 
|---|
| 273 | Break; | 
|---|
| 274 | end; | 
|---|
| 275 |  | 
|---|
| 276 | '-' : | 
|---|
| 277 | begin{hyphenated words} | 
|---|
| 278 | if FSourceBuf[ FSourcePos + 1 ] in [ 'A'..'Z', 'a'..'z', '0'..'9', '_' ] then | 
|---|
| 279 | begin | 
|---|
| 280 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 281 | Inc( FSourcePos ); | 
|---|
| 282 | end | 
|---|
| 283 | else | 
|---|
| 284 | Break; | 
|---|
| 285 | end; | 
|---|
| 286 |  | 
|---|
| 287 | else | 
|---|
| 288 | Break; | 
|---|
| 289 | end;{case} | 
|---|
| 290 | end; | 
|---|
| 291 | FToken.TokenType := HR_TOKEN_TEXT_SYMBOL; | 
|---|
| 292 | Break;{out of repeat} | 
|---|
| 293 | end; | 
|---|
| 294 |  | 
|---|
| 295 | {numbers} | 
|---|
| 296 | if ( FSourceBuf[ FSourcePos ] in [ '0'..'9' ] ) or | 
|---|
| 297 | ( ( FSourceBuf[ FSourcePos ] = '-' ) and ( FSourceBuf[ FSourcePos + 1 ] in [ '.', '0'..'9' ] ) ) then | 
|---|
| 298 | begin | 
|---|
| 299 |  | 
|---|
| 300 | {integer numbers} | 
|---|
| 301 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 302 | Inc( FSourcePos ); | 
|---|
| 303 | while FSourceBuf[ FSourcePos ] in [ '0'..'9' ] do | 
|---|
| 304 | begin | 
|---|
| 305 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 306 | Inc( FSourcePos ); | 
|---|
| 307 | FToken.TokenType := HR_TOKEN_TEXT_INTEGER; | 
|---|
| 308 | end; | 
|---|
| 309 |  | 
|---|
| 310 | {floating point numbers} | 
|---|
| 311 | while ( FSourceBuf[ FSourcePos ] in [ '0'..'9', 'e', 'E', '+', '-' ] ) or | 
|---|
| 312 | ( ( FSourceBuf[ FSourcePos ] = '.') and ( FSourceBuf[ FSourcePos + 1 ] <> '.' ) ) do | 
|---|
| 313 | begin | 
|---|
| 314 | FTokenBuf.Write( FSourceBuf[ FSourcePos ] ); | 
|---|
| 315 | Inc( FSourcePos ); | 
|---|
| 316 | FToken.TokenType := HR_TOKEN_TEXT_FLOAT; | 
|---|
| 317 | end; | 
|---|
| 318 |  | 
|---|
| 319 | Break;{out of repeat} | 
|---|
| 320 | end; | 
|---|
| 321 |  | 
|---|
| 322 | inherited GetNextToken; | 
|---|
| 323 | {Break;}{out of repeat} | 
|---|
| 324 |  | 
|---|
| 325 | until( True ); | 
|---|
| 326 | end; | 
|---|
| 327 |  | 
|---|
| 328 |  | 
|---|
| 329 | end. | 
|---|
| 330 |  | 
|---|