Changeset 72 for branches/Transpascal/Compiler/Analyze/UParser.pas
- Timestamp:
- Oct 20, 2010, 11:02:10 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/Transpascal/Compiler/Analyze/UParser.pas
r71 r72 6 6 7 7 uses 8 SysUtils, Variants, Classes, 8 SysUtils, Variants, Classes, Contnrs, 9 9 Dialogs, USourceCode, FileUtil; 10 10 … … 19 19 ttOperator, ttEndOfFile, ttLineComment, ttBlockComment1, ttBlockComment2, 20 20 ttUnknown, ttWhiteSpace); 21 22 TToken = class 23 Token: string; 24 CodePosition: TPoint; 25 TokenType: TTokenType; 26 end; 21 27 22 28 { TBaseParser } … … 29 35 FNextTokenType: TTokenType; 30 36 FParserState: TParserState; 31 PreviousChar: char; 32 CurrentChar: char; 37 PreviousChar: Char; 38 CurrentChar: Char; 39 TokenCodePosition: TPoint; 40 procedure GetNextToken; 33 41 public 34 42 ProgramCode: TProgram; 35 CodeStreamPosition: integer;43 CodeStreamPosition: Integer; 36 44 CodePosition: TPoint; 37 LastTokenEnd: TPoint;38 LastTokenStart: TPoint;39 45 SourceCodeText: TStringList; 46 Tokens: TObjectList; // TObjectList<TToken> 47 TokenIndex: Integer; 48 constructor Create; 49 destructor Destroy; override; 40 50 function IsAlphanumeric(Character: char): boolean; 41 procedure GetNextToken;42 function ReadCode: string;43 function NextToken: string;44 function NextTokenType: TTokenType;45 procedure Expect(Code: string);46 51 function IsWhiteSpace(Character: char): boolean; 47 52 function IsAlphabetic(Character: char): boolean; … … 49 54 function IsKeyword(Text: string): boolean; 50 55 function IsOperator(Text: string): boolean; 51 procedure Log(Text: string); 52 procedure ErrorMessage(const Text: string; const Arguments: array of const); 56 function ReadCode: string; 57 function NextToken: string; 58 function NextTokenType: TTokenType; 59 procedure Expect(Code: string); 60 procedure ErrorMessage(const Text: string; const Arguments: array of const; 61 TokenOffset: Integer); 53 62 property OnErrorMessage: TOnErrorMessage read FOnErrorMessage write FOnErrorMessage; 54 procedure Init;63 procedure Process; 55 64 property FileName: string read FFileName write FFileName; 56 65 end; 57 66 58 67 resourcestring 59 SUnknownIdentifier = 'Unknown identificator "%s".';60 SIllegalExpression = 'Illegal expression "%s".';61 68 SExpectedButFound = 'Expected "%s" but "%s" found.'; 62 SRedefineIdentifier = 'Identificator "%s" redefinition.';63 STypeNotDefined = 'Type "%s" not defined.';64 SEndOfDataReached = 'Parser reached to end of input data.';65 SUndefinedVariable = 'Undefined variable "%s".';66 SUndefinedType = 'Undefined type "%s".';67 SUndefinedConstant = 'Undefined constant "%s".';68 SUnitNotFound = 'Unit "%s" not found.';69 69 70 70 implementation … … 72 72 { TBaseParser } 73 73 74 procedure TBaseParser.ErrorMessage(const Text: string; const Arguments: array of const); 74 procedure TBaseParser.ErrorMessage(const Text: string; const Arguments: array of const; 75 TokenOffset: Integer); 75 76 begin 76 77 if Assigned(FOnErrorMessage) then 77 FOnErrorMessage(Format(Text, Arguments), LastTokenStart, FileName); 78 if (TokenIndex + TokenOffset) < Tokens.Count then begin 79 FOnErrorMessage(Format(Text, Arguments), 80 TToken(Tokens[TokenIndex + TokenOffset]).CodePosition, FileName); 81 end; 78 82 end; 79 83 80 84 procedure TBaseParser.Expect(Code: string); 81 85 begin 82 Log('Expected: ' + Code + ' Readed: ' + FNextToken); 83 if FNextToken <> Code then begin 84 //ReadCode; 85 ErrorMessage(SExpectedButFound, [Code, FNextToken]); 86 if NextToken <> Code then begin 87 ErrorMessage(SExpectedButFound, [Code, FNextToken], -2); 86 88 87 89 // Recovery: try to find nearest same code 88 while ( FNextToken <> Code) and (FNextTokenType <> ttEndOfFile) do89 GetNextToken;90 end; 91 GetNextToken;90 while (NextToken <> Code) and (NextTokenType <> ttEndOfFile) do 91 ReadCode; 92 end; 93 ReadCode; 92 94 end; 93 95 … … 95 97 begin 96 98 Result := (Character in ['a'..'z']) or (Character in ['A'..'Z']); 99 end; 100 101 constructor TBaseParser.Create; 102 begin 103 Tokens := TObjectList.Create; 104 end; 105 106 destructor TBaseParser.Destroy; 107 begin 108 Tokens.Free; 109 inherited Destroy; 97 110 end; 98 111 … … 144 157 end; 145 158 146 procedure TBaseParser.Log(Text: string); 147 const 148 LogFileName = 'ParseLog.txt'; 149 var 150 LogFile: TFileStream; 151 begin 152 try 153 if FileExistsUTF8(LogFileName) { *Converted from FileExists* } then 154 LogFile := TFileStream.Create(LogFileName, fmOpenWrite) 155 else 156 LogFile := TFileStream.Create(LogFileName, fmCreate); 157 if Length(Text) > 0 then 158 begin 159 LogFile.Write(Text[1], Length(Text)); 160 LogFile.Write(#13#10, 2); 161 end; 162 finally 163 LogFile.Free; 164 end; 165 end; 166 167 procedure TBaseParser.Init; 168 begin 169 CodePosition := Point(1, 1); 159 procedure TBaseParser.Process; 160 var 161 NewToken: TToken; 162 begin 163 CodePosition := Point(0, 1); 170 164 CurrentChar := #0; 171 165 PreviousChar := #0; … … 173 167 FNextTokenType := ttNone; 174 168 CodeStreamPosition := 1; 175 GetNextToken; 169 Tokens.Clear; 170 TokenIndex := 0; 171 while CodeStreamPosition < Length(SourceCodeText.Text) do begin 172 NewToken := TToken.Create; 173 GetNextToken; 174 NewToken.CodePosition := TokenCodePosition; 175 NewToken.TokenType := FNextTokenType; 176 NewToken.Token := FNextToken; 177 Tokens.Add(NewToken); 178 end; 176 179 end; 177 180 … … 184 187 SpecChar: set of char = [';', '.', ',', ':', '(', ')', '[', ']', 185 188 '+', '-', '/', '*', '^', '=', '<', '>', '@']; 186 DoubleSpecChar: array[0..6] of string = (':=', '..', '<=', '>=', '<>', '+=', '-='); 187 begin 188 LastTokenStart := LastTokenEnd; 189 LastTokenEnd := CodePosition; 189 DoubleSpecChar: array[0..6] of string = (':=', '..', '<=', '>=', '<>', 190 '+=', '-='); 191 begin 190 192 FNextToken := ''; 191 193 FNextTokenType := ttNone; 192 194 FParserState := psNone; 193 195 with SourceCodeText do 194 while True do 195 begin 196 while True do begin 196 197 if CodeStreamPosition < Length(Text) then begin 197 198 CurrentChar := Text[CodeStreamPosition]; … … 204 205 205 206 if FParserState = psNone then begin 207 TokenCodePosition := CodePosition; 206 208 if IsWhiteSpace(CurrentChar) then 207 209 FParserState := psWhiteSpace … … 293 295 Inc(CodePosition.X); 294 296 if (CurrentChar = #13) then begin 295 CodePosition.X := 1;297 CodePosition.X := 0; 296 298 Inc(CodePosition.Y); 297 299 end; … … 305 307 function TBaseParser.ReadCode: string; 306 308 begin 307 Result := FNextToken; 308 GetNextToken; 309 Log('Read: ' + Result); 309 if TokenIndex < Tokens.Count then begin 310 Result := TToken(Tokens[TokenIndex]).Token; 311 Inc(TokenIndex); 312 end else Result := ''; 310 313 end; 311 314 312 315 function TBaseParser.NextToken: string; 313 316 begin 314 Result := FNextToken; 317 if TokenIndex < Tokens.Count then begin 318 Result := TToken(Tokens[TokenIndex]).Token; 319 end else Result := ''; 315 320 end; 316 321 317 322 function TBaseParser.NextTokenType: TTokenType; 318 323 begin 319 Result := FNextTokenType; 324 if TokenIndex < Tokens.Count then begin 325 Result := TToken(Tokens[TokenIndex]).TokenType; 326 end else Result := ttEndOfFile; 320 327 end; 321 328
Note:
See TracChangeset
for help on using the changeset viewer.