parser.inc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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', '+', '-'] do
  207. begin
  208. Inc(P);
  209. Result := toFloat;
  210. end;
  211. end;
  212. else
  213. Result := P^;
  214. if Result <> toEOF then Inc(P);
  215. end;
  216. FSourcePtr := P;
  217. FToken := Result;
  218. end;
  219. Function TParser.SourcePos: Longint;
  220. begin
  221. Result := FOrigin + (FTokenPtr - FBuffer);
  222. end;
  223. Function TParser.TokenComponentIdent: String;
  224. var
  225. P : PChar;
  226. begin
  227. CheckToken(toSymbol);
  228. P := FSourcePtr;
  229. while P^ = '.' do
  230. begin
  231. Inc(P);
  232. if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
  233. Error(SIdentifierExpected);
  234. repeat
  235. Inc(P)
  236. until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  237. end;
  238. FSourcePtr := P;
  239. Result := TokenString;
  240. end;
  241. Function TParser.TokenFloat: Extended;
  242. var
  243. FloatError : Integer;
  244. Back : Real;
  245. begin
  246. Result := 0;
  247. Val(TokenString, Back, FloatError);
  248. Result := Back;
  249. end;
  250. Function TParser.TokenInt: Longint;
  251. begin
  252. Result := StrToInt(TokenString);
  253. end;
  254. Function TParser.TokenString: string;
  255. var
  256. L : Integer;
  257. StrBuf : array[0..1023] of Char;
  258. begin
  259. if FToken = toString then begin
  260. L := FStringPtr - FTokenPtr
  261. end else begin
  262. L := FSourcePtr - FTokenPtr;
  263. end;
  264. StrLCopy(StrBuf, FTokenPtr, L);
  265. Result := StrPas(StrBuf);
  266. end;
  267. Function TParser.TokenSymbolIs(const S: string): Boolean;
  268. begin
  269. Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
  270. end;
  271. {
  272. $Log$
  273. Revision 1.2 2000-07-13 11:32:59 michael
  274. + removed logs
  275. }