19
19
ParseBufSize = 4096;
21
procedure TParser.ReadBuffer;
22
TokNames : array[0..LastSpecialToken] of string =
32
function TParser.GetTokenName(aTok: char): string;
34
if ord(aTok) <= LastSpecialToken then
35
Result:=TokNames[ord(aTok)]
39
procedure TParser.LoadBuffer;
42
toread:=fStream.Size-fStream.Position;
43
if toread>ParseBufSize then toread:=ParseBufSize;
49
fStream.ReadBuffer(fBuf[0],toread);
56
procedure TParser.CheckLoadBuffer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
58
if fBuf[fPos]=#0 then LoadBuffer;
61
procedure TParser.ProcessChar; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
63
fLastTokenStr:=fLastTokenStr+fBuf[fPos];
68
function TParser.IsNumber: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
70
Result:=fBuf[fPos] in ['0'..'9'];
73
function TParser.IsHexNum: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
75
Result:=fBuf[fPos] in ['0'..'9','A'..'F','a'..'f'];
78
function TParser.IsAlpha: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
80
Result:=fBuf[fPos] in ['_','A'..'Z','a'..'z'];
83
function TParser.IsAlphaNum: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
85
Result:=IsAlpha or IsNumber;
88
function TParser.GetHexValue(c: char): byte; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
91
'0'..'9' : Result:=ord(c)-$30;
92
'A'..'F' : Result:=ord(c)-$37; //-$41+$0A
93
'a'..'f' : Result:=ord(c)-$57; //-$61+$0A
97
function TParser.GetAlphaNum: string;
100
ErrorFmt(SParExpected,[GetTokenName(toSymbol)]);
104
Result:=Result+fBuf[fPos];
110
procedure TParser.HandleNewLine;
112
if fBuf[fPos]=#13 then //CR
116
if fBuf[fPos]=#10 then inc(fPos); //CR LF
120
fDeltaPos:=-(fPos-1);
123
procedure TParser.SkipSpaces;
125
while fBuf[fPos] in [' ',#9] do
129
procedure TParser.SkipWhitespace;
136
#10,#13 : HandleNewLine
142
procedure TParser.HandleEof;
148
procedure TParser.HandleAlphaNum;
150
fLastTokenStr:=GetAlphaNum;
154
procedure TParser.HandleNumber;
156
floatPunct = (fpDot,fpE);
157
floatPuncts = set of floatPunct;
159
allowed : floatPuncts;
25
Inc(FOrigin, FSourcePtr - FBuffer);
27
FSourceEnd[0] := FSaveChar;
28
Count := FBufPtr - FSourcePtr;
31
Move(FSourcePtr[0], FBuffer[0], Count);
34
FBufPtr := FBuffer + Count;
35
Inc(FBufPtr, FStream.Read(FBufPtr[0], FBufEnd - FBufPtr));
37
FSourcePtr := FBuffer;
38
FSourceEnd := FBufPtr;
39
if (FSourceEnd = FBufEnd) then
41
FSourceEnd := LineStart(FBuffer, FSourceEnd - 1);
42
if FSourceEnd = FBuffer then
165
if (fBuf[fPos] in ['.','e','E']) then
168
allowed:=[fpDot,fpE];
169
while (fBuf[fPos] in ['.','e','E','0'..'9']) do
47
FSaveChar := FSourceEnd[0];
51
procedure TParser.SkipBlanks;
53
while FSourcePtr^ < #33 do begin
54
if FSourcePtr^ = #0 then begin
56
if FSourcePtr^ = #0 then exit;
58
end else if FSourcePtr^ = #10 then Inc(FSourceLine);
172
'.' : if fpDot in allowed then Exclude(allowed,fpDot) else break;
173
'E','e' : if fpE in allowed then
177
if (fBuf[fPos] in ['+','-']) then ProcessChar;
178
if not (fBuf[fPos] in ['0'..'9']) then
179
ErrorFmt(SParInvalidFloat,[fLastTokenStr+fBuf[fPos]]);
186
if (fBuf[fPos] in ['s','S','d','D','c','C']) then //single, date, currency
188
fFloatType:=fBuf[fPos];
195
procedure TParser.HandleHexNumber;
208
ErrorFmt(SParInvalidInteger,[fLastTokenStr]);
212
function TParser.HandleQuotedString: string;
220
#0 : ErrorStr(SParUnterminatedString);
221
#13,#10 : ErrorStr(SParUnterminatedString);
225
if fBuf[fPos]<>'''' then exit;
228
Result:=Result+fBuf[fPos];
234
function TParser.HandleDecimalString(var ascii : boolean): widestring;
242
Result:=Result+fBuf[fPos];
246
if not TryStrToInt(Result,i) then
248
if i>127 then ascii:=false;
250
Result[1]:=widechar(word(i));
253
procedure TParser.HandleString;
260
'''' : fLastTokenWStr:=fLastTokenWStr+HandleQuotedString;
261
'#' : fLastTokenWStr:=fLastTokenWStr+HandleDecimalString(ascii)
268
fLastTokenStr:=fLastTokenWStr;
271
procedure TParser.HandleMinus;
278
fLastTokenStr:='-'+fLastTokenStr;
283
fLastTokenStr:=fToken;
287
procedure TParser.HandleUnknown;
290
fLastTokenStr:=fToken;
63
294
constructor TParser.Create(Stream: TStream);
68
GetMem(FBuffer, ParseBufSize);
72
FBufEnd := FBuffer + ParseBufSize;
73
FSourcePtr := FBuffer;
74
FSourceEnd := FBuffer;
297
fBuf:=GetMem(ParseBufSize+1);
82
311
destructor TParser.Destroy;
84
if Assigned(FBuffer) then
86
FStream.Seek(PtrInt(FTokenPtr) - PtrInt(FBufPtr), 1);
87
FreeMem(FBuffer, ParseBufSize);
313
fStream.Position:=SourcePos;
93
procedure TParser.CheckToken(T : Char);
317
procedure TParser.CheckToken(T: Char);
99
Error(SIdentifierExpected);
101
Error(SStringExpected);
103
Error(SNumberExpected);
105
ErrorFmt(SCharExpected, [T]);
320
ErrorFmt(SParWrongTokenType,[GetTokenName(T),GetTokenName(fToken)]);
110
323
procedure TParser.CheckTokenSymbol(const S: string);
112
if not TokenSymbolIs(S) then
113
ErrorFmt(SSymbolExpected, [S]);
325
CheckToken(toSymbol);
326
if CompareText(fLastTokenStr,S)<>0 then
327
ErrorFmt(SParWrongTokenSymbol,[s,fLastTokenStr]);
116
Procedure TParser.Error(const Ident: string);
330
procedure TParser.Error(const Ident: string);
121
Procedure TParser.ErrorFmt(const Ident: string; const Args: array of const);
123
ErrorStr(Format(Ident, Args));
126
Procedure TParser.ErrorStr(const Message: string);
128
raise EParserError.CreateFmt(SParseError, [Message, FSourceLine]);
335
procedure TParser.ErrorFmt(const Ident: string; const Args: array of const);
337
ErrorStr(Format(Ident,Args));
340
procedure TParser.ErrorStr(const Message: string);
342
raise EParserError.CreateFmt(Message+SParLocInfo,[SourceLine,fPos+fDeltaPos,SourcePos]);
132
345
procedure TParser.HexToBinary(Stream: TStream);
134
function HexDigitToInt(c: Char): Integer;
346
var outbuf : array[0..ParseBufSize-1] of byte;
136
if (c >= '0') and (c <= '9') then Result := Ord(c) - Ord('0')
137
else if (c >= 'A') and (c <= 'F') then Result := Ord(c) - Ord('A') + 10
138
else if (c >= 'a') and (c <= 'f') then Result := Ord(c) - Ord('a') + 10
143
buf: array[0..255] of Byte;
148
while FSourcePtr^ <> '}' do begin
151
digit1 := HexDigitToInt(FSourcePtr[0]);
152
if digit1 < 0 then break;
153
buf[bytes] := digit1 shl 4 or HexDigitToInt(FSourcePtr[1]);
354
b:=(GetHexValue(fBuf[fPos]) shl 4);
358
Error(SParUnterminatedBinValue);
359
b:=b or GetHexValue(fBuf[fPos]);
363
if i>=ParseBufSize then
365
Stream.WriteBuffer(outbuf[0],i);
157
if bytes = 0 then Error(SInvalidBinary);
158
Stream.Write(buf, bytes);
371
Stream.WriteBuffer(outbuf[0],i);
375
function TParser.NextToken: Char;
165
Function TParser.NextToken: Char;
169
procedure PutChar(achar: Word);
172
if length(fString) < CharCount then begin
173
setlength(fString,length(fString) + length(fString) div 4 + 64);
175
fString[CharCount]:= WideChar(achar);
186
'A'..'Z', 'a'..'z', '_':
189
while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
201
while P^ in ['0'..'9'] do
203
I := I * 10 + (Ord(P^) - Ord('0'));
215
Error(SInvalidString);
219
if P^ <> '''' then Break;
229
setlength(fString,CharCount);
235
while P^ in ['0'..'9', 'A'..'F', 'a'..'f'] do Inc(P);
241
while P^ in ['0'..'9'] do Inc(P);
243
while (P^ in ['0'..'9', '.', 'e', 'E', '+', '-']) and not
244
((P[0] = '.') and not (P[1] in ['0'..'9', 'e', 'E'])) do
252
if Result <> toEOF then Inc(P);
258
Function TParser.SourcePos: Longint;
260
Result := FOrigin + (FTokenPtr - FBuffer);
264
Function TParser.TokenComponentIdent: String;
268
CheckToken(toSymbol);
383
'_','A'..'Z','a'..'z' : HandleAlphaNum;
384
'$' : HandleHexNumber;
386
'0'..'9' : HandleNumber;
387
'''','#' : HandleString
394
function TParser.SourcePos: Longint;
396
Result:=fStream.Position-fBufLen+fPos;
399
function TParser.TokenComponentIdent: string;
401
if fToken<>toSymbol then
402
ErrorFmt(SParExpected,[GetTokenName(toSymbol)]);
404
while fBuf[fPos]='.' do
274
if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
275
Error(SIdentifierExpected);
278
until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
407
fLastTokenStr:=fLastTokenStr+GetAlphaNum;
281
Result := TokenString;
409
Result:=fLastTokenStr;
284
412
Function TParser.TokenFloat: Extended;
286
I,FloatError : Integer;
293
// Convert , decimal separator to ., handle backwards compatibility streams.
294
for I:=1 to Length(S) do
297
Val(S, Back, FloatError);
301
Function TParser.TokenInt: Longint;
303
Result := StrToInt(TokenString);
306
Function TParser.TokenString: string;
310
if FToken = toString then begin
313
L := FSourcePtr - FTokenPtr;
316
Move(FTokenPtr^,Result[1],L);
417
Val(fLastTokenStr,Result,errcode);
419
ErrorFmt(SParInvalidFloat,[fLastTokenStr]);
422
Function TParser.TokenInt: Int64;
424
if not TryStrToInt64(fLastTokenStr,Result) then
425
Result:=Int64(StrToQWord(fLastTokenStr)); //second chance for malformed files
428
function TParser.TokenString: string;
431
toWString : Result:=fLastTokenWStr;
432
toFloat : if fFloatType<>#0 then
433
Result:=fLastTokenStr+fFloatType
434
else Result:=fLastTokenStr
436
Result:=fLastTokenStr;
320
Function TParser.TokenWideString: widestring;
440
function TParser.TokenWideString: WideString;
322
if FToken = toString then
442
if fToken=toWString then
443
Result:=fLastTokenWStr
445
Result:=fLastTokenStr;
329
Function TParser.TokenSymbolIs(const S: string): Boolean;
448
function TParser.TokenSymbolIs(const S: string): Boolean;
331
Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
450
Result:=(fToken=toSymbol) and (CompareText(fLastTokenStr,S)=0);