parser.inc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TParser *}
  13. {****************************************************************************}
  14. const
  15. ParseBufSize = 4096;
  16. procedure TParser.ReadBuffer;
  17. var
  18. Count : Integer;
  19. begin
  20. Inc(FOrigin, FSourcePtr - FBuffer);
  21. FSourceEnd[0] := FSaveChar;
  22. Count := FBufPtr - FSourcePtr;
  23. if Count <> 0 then
  24. begin
  25. Move(FSourcePtr[0], FBuffer[0], Count);
  26. end;
  27. FBufPtr := FBuffer + Count;
  28. Inc(FBufPtr, FStream.Read(FBufPtr[0], FBufEnd - FBufPtr));
  29. FSourcePtr := FBuffer;
  30. FSourceEnd := FBufPtr;
  31. if (FSourceEnd = FBufEnd) then
  32. begin
  33. FSourceEnd := LineStart(FBuffer, FSourceEnd - 1);
  34. if FSourceEnd = FBuffer then
  35. begin
  36. Error(SLineTooLong);
  37. end;
  38. end;
  39. FSaveChar := FSourceEnd[0];
  40. FSourceEnd[0] := #0;
  41. end;
  42. procedure TParser.SkipBlanks;
  43. begin
  44. while FSourcePtr^ < #33 do begin
  45. if FSourcePtr^ = #0 then begin
  46. ReadBuffer;
  47. if FSourcePtr^ = #0 then exit;
  48. continue;
  49. end else if FSourcePtr^ = #10 then Inc(FSourceLine);
  50. Inc(FSourcePtr);
  51. end;
  52. end;
  53. constructor TParser.Create(Stream: TStream);
  54. begin
  55. inherited Create;
  56. FStream := Stream;
  57. GetMem(FBuffer, ParseBufSize);
  58. FBuffer[0] := #0;
  59. FBufPtr := FBuffer;
  60. FBufEnd := FBuffer + ParseBufSize;
  61. FSourcePtr := FBuffer;
  62. FSourceEnd := FBuffer;
  63. FTokenPtr := FBuffer;
  64. FSourceLine := 1;
  65. NextToken;
  66. end;
  67. destructor TParser.Destroy;
  68. begin
  69. if Assigned(FBuffer) then
  70. begin
  71. FStream.Seek(Longint(FTokenPtr) - Longint(FBufPtr), 1);
  72. FreeMem(FBuffer, ParseBufSize);
  73. end;
  74. inherited Destroy;
  75. end;
  76. procedure TParser.CheckToken(T : Char);
  77. begin
  78. if Token <> T then
  79. begin
  80. case T of
  81. toSymbol:
  82. Error(SIdentifierExpected);
  83. toString:
  84. Error(SStringExpected);
  85. toInteger, toFloat:
  86. Error(SNumberExpected);
  87. else
  88. ErrorFmt(SCharExpected, [T]);
  89. end;
  90. end;
  91. end;
  92. procedure TParser.CheckTokenSymbol(const S: string);
  93. begin
  94. if not TokenSymbolIs(S) then
  95. ErrorFmt(SSymbolExpected, [S]);
  96. end;
  97. Procedure TParser.Error(const Ident: string);
  98. begin
  99. ErrorStr(Ident);
  100. end;
  101. Procedure TParser.ErrorFmt(const Ident: string; const Args: array of const);
  102. begin
  103. ErrorStr(Format(Ident, Args));
  104. end;
  105. Procedure TParser.ErrorStr(const Message: string);
  106. begin
  107. raise EParserError.CreateFmt(SParseError, [Message, FSourceLine]);
  108. end;
  109. procedure TParser.HexToBinary(Stream: TStream);
  110. function HexDigitToInt(c: Char): Integer;
  111. begin
  112. if (c >= '0') and (c <= '9') then Result := Ord(c) - Ord('0')
  113. else if (c >= 'A') and (c <= 'F') then Result := Ord(c) - Ord('A') + 10
  114. else if (c >= 'a') and (c <= 'f') then Result := Ord(c) - Ord('a') + 10
  115. else Result := -1;
  116. end;
  117. var
  118. buf: array[0..255] of Byte;
  119. digit1: Integer;
  120. bytes: Integer;
  121. begin
  122. SkipBlanks;
  123. while FSourcePtr^ <> '}' do begin
  124. bytes := 0;
  125. while True do begin
  126. digit1 := HexDigitToInt(FSourcePtr[0]);
  127. if digit1 < 0 then break;
  128. buf[bytes] := digit1 shl 4 or HexDigitToInt(FSourcePtr[1]);
  129. Inc(FSourcePtr, 2);
  130. Inc(bytes);
  131. end;
  132. if bytes = 0 then Error(SInvalidBinary);
  133. Stream.Write(buf, bytes);
  134. SkipBlanks;
  135. end;
  136. NextToken;
  137. end;
  138. Function TParser.NextToken: Char;
  139. var
  140. I : Integer;
  141. P, S : PChar;
  142. begin
  143. SkipBlanks;
  144. P := FSourcePtr;
  145. FTokenPtr := P;
  146. case P^ of
  147. 'A'..'Z', 'a'..'z', '_':
  148. begin
  149. Inc(P);
  150. while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
  151. Result := toSymbol;
  152. end;
  153. '#', '''':
  154. begin
  155. S := P;
  156. while True do
  157. case P^ of
  158. '#':
  159. begin
  160. Inc(P);
  161. I := 0;
  162. while P^ in ['0'..'9'] do
  163. begin
  164. I := I * 10 + (Ord(P^) - Ord('0'));
  165. Inc(P);
  166. end;
  167. S^ := Chr(I);
  168. Inc(S);
  169. end;
  170. '''':
  171. begin
  172. Inc(P);
  173. while True do
  174. begin
  175. case P^ of
  176. #0, #10, #13:
  177. Error(SInvalidString);
  178. '''':
  179. begin
  180. Inc(P);
  181. if P^ <> '''' then Break;
  182. end;
  183. end;
  184. S^ := P^;
  185. Inc(S);
  186. Inc(P);
  187. end;
  188. end;
  189. else
  190. Break;
  191. end;
  192. FStringPtr := S;
  193. Result := toString;
  194. end;
  195. '$':
  196. begin
  197. Inc(P);
  198. while P^ in ['0'..'9', 'A'..'F', 'a'..'f'] do Inc(P);
  199. Result := toInteger;
  200. end;
  201. '-', '0'..'9':
  202. begin
  203. Inc(P);
  204. while P^ in ['0'..'9'] do Inc(P);
  205. Result := toInteger;
  206. while (P^ in ['0'..'9', '.', 'e', 'E', '+', '-']) and not
  207. ((P[0] = '.') and not (P[1] in ['0'..'9', 'e', 'E'])) do
  208. begin
  209. Inc(P);
  210. Result := toFloat;
  211. end;
  212. end;
  213. else
  214. Result := P^;
  215. if Result <> toEOF then Inc(P);
  216. end;
  217. FSourcePtr := P;
  218. FToken := Result;
  219. end;
  220. Function TParser.SourcePos: Longint;
  221. begin
  222. Result := FOrigin + (FTokenPtr - FBuffer);
  223. end;
  224. Function TParser.TokenComponentIdent: String;
  225. var
  226. P : PChar;
  227. begin
  228. CheckToken(toSymbol);
  229. P := FSourcePtr;
  230. while P^ = '.' do
  231. begin
  232. Inc(P);
  233. if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
  234. Error(SIdentifierExpected);
  235. repeat
  236. Inc(P)
  237. until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  238. end;
  239. FSourcePtr := P;
  240. Result := TokenString;
  241. end;
  242. Function TParser.TokenFloat: Extended;
  243. var
  244. FloatError : Integer;
  245. Back : Real;
  246. begin
  247. Result := 0;
  248. Val(TokenString, Back, FloatError);
  249. Result := Back;
  250. end;
  251. Function TParser.TokenInt: Longint;
  252. begin
  253. Result := StrToInt(TokenString);
  254. end;
  255. Function TParser.TokenString: string;
  256. var
  257. L : Integer;
  258. StrBuf : array[0..1023] of Char;
  259. begin
  260. if FToken = toString then begin
  261. L := FStringPtr - FTokenPtr
  262. end else begin
  263. L := FSourcePtr - FTokenPtr;
  264. end;
  265. StrLCopy(StrBuf, FTokenPtr, L);
  266. Result := StrPas(StrBuf);
  267. end;
  268. Function TParser.TokenSymbolIs(const S: string): Boolean;
  269. begin
  270. Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
  271. end;
  272. {
  273. $Log$
  274. Revision 1.4 2002-09-07 15:15:24 peter
  275. * old logs removed and tabs fixed
  276. }