📄 uwparser.pas
字号:
end;
10: begin // final state 10 represents a read special char
EAToken := ttSpecialChar;
Break;
end;
12: begin // final state 12 represents a read comment
EAToken := ttComment;
Break;
end;
15: begin // final state 15 represents a read hexadecimal number
EAToken := ttHexdecimal;
Break;
end;
98: begin // final state 98 represents a lexical error
EAToken := ttError;
Break;
end;
99: begin // final state 99 represents the end of the source stream
EAToken := ttEOF;
Break;
end;
end;
end;
end;
end;
// restart a fomerly broken analysis phase
procedure TWParser.Restart;
var NewToken: TToken; // the last read token
ListToken: TToken; // copy of the read token that is added to the list of token
AddToList: Boolean; // add a new token to the token list (result from user event)
Stop: Boolean; // analysis break (result from user event)
begin
Eof := false; // now end of stream is not yet reached
Stop := False; // initialize abort flag
NewToken := TToken.Create; // create the token structure
repeat // repeat until ttEOF Token is read
ReadToken; // read the next token
NewToken.Token := EAToken; // save the read token
if NewToken.Token = ttComment then
NewToken.SubType := EASubType // save the read token sub-type
else
NewToken.SubType := tsNone;
NewToken.Text := EAText; // save the belonging text
NewToken.Row := EARow; // save column
NewToken.Column := EAColumn; // save row
NewToken.Position := EAPosition; // save the position within the stream
NewToken.Tag := 0; // initialize the user information
// if an identifier is read and the belonging text is a keyword
// then change the token type into ttKeyword
if (NewToken.Token=ttIdentifier) and IsKeyword(NewToken.Text) then begin
NewToken.Token := ttKeyword;
end;
// if an identifier is read and no identifiers are allowed then
// the token type is changed to ttError
if (NewToken.Token = ttIdentifier) and (not FAllowIdentifier) then begin
NewToken.Token := ttError;
end;
AddToList := true; // default is add the new token to the list of tokens
// if a user defined event is available this event is called before the
// token is put in the tokenlist
if Assigned( FOnTokenRead ) then begin
FOnTokenRead( Self, NewToken, AddToList, Stop );
end;
if AddToList then begin
ListToken := TToken.Create; // create a new token for the list of tokens
ListToken.CopyFrom( NewToken ); // copy the contents of the read token
TokenList.Add( ListToken ); // put the token in the tokenlist
end;
until (EAToken = ttEof) or (Stop); // until ttEOF is read or abort flag is set
NewToken.Free;
end;
// the user defines the additional chars for identifier in a string. this
// string must be converted into a set of char.
procedure TWParser.SetAdditionalChars( Value: string );
var i: Integer;
begin
FIdentChars := ['a'..'z', 'A'..'Z']; // first all letters are allowed
for i := 1 to Length(Value) do begin // for every char in the string
FIdentChars := FIdentChars + [Value[i]]; // add the char to the set
end;
end;
// this method seems to be unnecessary, but it is very important for
// the correct work of TStringList in the object inspector
procedure TWParser.SetKeywords( Value: TStringList );
begin
FKeywords.Assign( Value );
end;
// the user defines the special char in a string. this string must be converted
// into a set of char. working with a set of char is much easier, but i
// do not want to implement a new property editor for die usage with the
// object inspector
procedure TWParser.SetSpecialChars( Value: string );
var i: Integer;
begin
FCharacters := []; // first the set of char is empty
for i := 1 to Length(Value) do begin // for every char in the string
FCharacters := FCharacters + [Value[i]]; // add the char to the set
end;
end;
// skip the next count chars from the source stream
procedure TWParser.SkipChars( Count: Integer );
var i: Integer;
ch: Char;
begin
for i := 1 to Count do begin
ReadCh( ch );
end;
end;
// the following methods are characterizing the internal state machine
// process a char if the state machine has the state 0
// state 0 is the starting state
procedure TWParser.EASwitch0( ch: Char );
begin
if Eof then begin // if the end of source stream is reached
EAState := 99; // switch to state 99
end else begin
if ch in FIdentChars then begin
EAState := 1;
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar;
end else begin
case ch of
'$' : begin // if a '$' is available switch to state 16
EAState := 16; // and try to read a hex number or a spacial char
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar;
end;
'0' : begin // if a '0' is read switch to state 13
EAState := 13; // and try to read an integer, real or hex number
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar;
end;
'1'..'9' : begin // if number is read switch to state 3
EAState := 3; // and try to read a integer or a floting point number
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar;
end;
'''' : begin // if the char ' is read switch to state 7
EAState := 7; // and try to read a string limited by '
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ReadCh( ch );
end;
'"' : begin // if the char " is read switch to state 9
EAState := 9; // and try to read a string limited by "
EARow := SourceY;
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ReadCh( ch );
end;
else begin
if ch in WhiteSpace then begin // if a white space is read
if SourceStream.Position < SourceStream.Size then
ReadCh( ch ) // read the next char
else
begin
EAState := 99;
end;
// if a comment beginning is defined and if the next chars corresend to
// the defined comment line begin
end
else
if (Length(FCommentLine) <> 0) and
(EqualStr(LookAHeadStr(Length(FCommentLine)), FCommentLine))
then begin
EAState := 11; // switch to state 11
EASubType := tsCommentLine;
SkipChars( Length(FCommentLine ) ); // skip the comment line begin
EARow := SourceY; // save row, column and position
EAColumn := SourceX;
EAPosition := SourceStream.Position;
// if a blockcomment beginning is defined and if the next chars corresend to
// the defined block comment beginning
end
else
if (Length(FComment1Begin) <> 0) and
(EqualStr(LookAHeadStr(Length(FComment1Begin)), FComment1Begin))
then begin
EAState := 18; // switch to state 18
EASubType := tsComment1Block;
SkipChars( Length(FComment1Begin ) ); // skip the comment block begin
EARow := SourceY; // save row, column and position
EAColumn := SourceX;
EAPosition := SourceStream.Position;
// if the actual char is a member of the special chars
end
else
if (Length(FComment2Begin) <> 0) and
(EqualStr(LookAHeadStr(Length(FComment2Begin)), FComment2Begin))
then begin
EAState := 19; // switch to state 19
EASubType := tsComment2Block;
SkipChars( Length(FComment2Begin ) ); // skip the comment block begin
EARow := SourceY; // save row, column and position
EAColumn := SourceX;
EAPosition := SourceStream.Position;
// if the actual char is a member of the special chars
end
else
if ch in FCharacters then begin
EAState := 10; // switch to state 10
EARow := SourceY; // save row, column and position
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar; // process this char
// else an illegal char is read and this will cause an error
end
else
begin
EAState := 98; // switch to state 98
EARow := SourceY; // save row, column ans position
EAColumn := SourceX;
EAPosition := SourceStream.Position;
ProcessChar; // process this char
end;
end;
end;
end;
end;
end;
// process a char if the state machine has the state 1.
// in this state the state machines tries to read an identifier. an identifier
// consists of a leading char and any following number or char
procedure TWParser.EASwitch1( ch: Char );
begin
if ch in FIdentChars then begin
ProcessChar; // every letter is a part of the identifier
end else if (FAllowFigures) and (ch in ['0'..'9']) then begin
ProcessChar; // if allowed every figures is a part of the identifier
end else begin
EAState := 2; // else switch to final state 2, identifier is complete
end;
end;
// process a char if the state machine has the state 3.
// in this state a integer or a floating point number is read
procedure TWParser.EASwitch3( ch: Char );
begin
case ch of
'0'..'9' : ProcessChar; // if a number is read the char is processed
'.',',' : if LookAheadStr(2)[2] in ['0'..'9'] then begin
// if a '.' or a ',' is read and the following char is a figure
// the char is processed
ProcessChar; // and the state is switched to state 5 in order
EAState := 5; // to read a floating point number
end else begin
EAState := 4; // the state is switched to final state 4 (integer)
end;
else EAState := 4; // the state is switched to final state 4 (integer)
end;
end;
// process a char if the state machine has the state 5.
// in this state floating point number is read
procedure TWParser.EASwitch5( ch: Char );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -