Jedi Code Format: Support escaped identifiers (&identifier). Issue #38067, patch from Domingo Galmés.

git-svn-id: trunk@64131 -
This commit is contained in:
juha 2020-11-13 09:37:02 +00:00
parent e405b8c6ac
commit c319bc8947
2 changed files with 92 additions and 46 deletions

View File

@ -1218,41 +1218,50 @@ begin
Recognise(ttEquals); Recognise(ttEquals);
//Recognise type helper (for fpc) repeat
if (fcTokenList.FirstSolidTokenType in [ttType,ttRecord]) and
(fcTokenList.SolidToken(2).TokenType=ttHelper) then
begin
RecogniseTypeHelper;
end else
// type or restricted type //Recognise type helper (for fpc)
if (fcTokenList.FirstSolidTokenType in [ttObject, ttClass, ttInterface, if (fcTokenList.FirstSolidTokenType in [ttType,ttRecord]) and
ttDispInterface]) then (fcTokenList.SolidToken(2).TokenType=ttHelper) then
RecogniseRestrictedType begin
else RecogniseTypeHelper;
RecogniseType; end else
if fcTokenList.FirstSolidTokenType = ttLessThan then
begin
RecogniseGenericType;
end;
if fcTokenList.FirstSolidTokenType = ttIs then // type or restricted type
begin if (fcTokenList.FirstSolidTokenType in [ttObject, ttClass, ttInterface,
Recognise(ttIs); ttDispInterface]) then
Recognise(ttNested); RecogniseRestrictedType
end; else
RecogniseType;
// the type can be deprecated if fcTokenList.FirstSolidTokenType = ttLessThan then
if fcTokenList.FirstSolidTokenType = ttDeprecated then begin
Recognise(ttDeprecated); RecogniseGenericType;
end;
if fcTokenList.FirstSolidTokenType = ttIs then
begin
Recognise(ttIs);
Recognise(ttNested);
end;
// the type can be deprecated
if fcTokenList.FirstSolidTokenType = ttDeprecated then
Recognise(ttDeprecated);
if fcTokenList.FirstSolidTokenType <> ttDot then
break;
Recognise(ttDot);
until false;
Recognise(ttSemicolon); Recognise(ttSemicolon);
PopNode; PopNode;
end; end;
function TBuildParseTree.GenericAhead: boolean; function TBuildParseTree.GenericAhead: boolean;
var var
liTokenIndex: integer; liTokenIndex: integer;
@ -5000,22 +5009,26 @@ begin
Recognise(IdentiferTokens); Recognise(IdentiferTokens);
{ tokens can be qualified by a unit name } { tokens can be qualified by a unit name }
{ can be nested types }
if pbCanHaveUnitQualifier and (fcTokenList.FirstSolidTokenType = ttDot) then if pbCanHaveUnitQualifier and (fcTokenList.FirstSolidTokenType = ttDot) then
begin begin
Recognise(ttDot); while fcTokenList.FirstSolidTokenType = ttDot do
begin
Recognise(ttDot);
{ delphi.net can preface the identifier with an '&' { delphi.net can preface the identifier with an '&'
in order to do something obscure with it - make it a literal or something in order to do something obscure with it - make it a literal or something
e.g. "WebRequest.&Create" is not a constructor, e.g. "WebRequest.&Create" is not a constructor,
but a C# method called "Create", which is not a reserved word in C# but a C# method called "Create", which is not a reserved word in C#
} }
RecognisePossiblyAmpdIdentifier; RecognisePossiblyAmpdIdentifier;
end;
end; end;
PopNode; PopNode;
end; end;
{ the name of a procedure/function/constructor can be { the name of a procedure/function/constructor can be
a plain name or classname.methodname a plain name or classname.methodname
@ -5125,9 +5138,14 @@ begin
// a use not a decl // a use not a decl
RecogniseGenericType; RecogniseGenericType;
end; end;
if fcTokenList.FirstSolidTokenType = ttDot then
begin
Recognise(ttDot);
RecogniseTypeId;
end;
end; end;
procedure TBuildParseTree.RecogniseAsmBlock; procedure TBuildParseTree.RecogniseAsmBlock;
begin begin
PushNode(nAsm); PushNode(nAsm);
@ -5432,7 +5450,7 @@ begin
begin begin
lcLastChar := lcNext.SourceCode[Length(lcNext.SourceCode)]; lcLastChar := lcNext.SourceCode[Length(lcNext.SourceCode)];
if (lcLastChar = 'h') then if ((lcLastChar = 'h') or (lcLastChar = 'H')) then
begin begin
Recognise(ttIdentifier); Recognise(ttIdentifier);
end; end;

View File

@ -124,6 +124,13 @@ begin
Result := IsMultiByte(pcChar); Result := IsMultiByte(pcChar);
end; end;
function CharIsOctDigit(const c: Char): Boolean;
const
OctDigits: set of Char = [ '0', '1', '2', '3', '4', '5', '6', '7'];
begin
Result := (c in OctDigits);
end;
{ TBuildTokenList } { TBuildTokenList }
constructor TBuildTokenList.Create; constructor TBuildTokenList.Create;
@ -468,14 +475,32 @@ end;
function TBuildTokenList.TryWord(const pcToken: TSourceToken): boolean; function TBuildTokenList.TryWord(const pcToken: TSourceToken): boolean;
begin begin
Result := False; Result := False;
if not CharIsWordChar(Current) then // support reserved words as identifiers
exit; // example.
// var &type:integer;
pcToken.SourceCode := Current; if Current='&' then
Consume; begin
if CharIsOctDigit(ForwardChar(1)) then
Exit;
pcToken.SourceCode := Current;
Consume;
if not CharIsWordChar(Current) then
begin
pcToken.TokenType := ttAmpersand;
exit;
end;
end
else
begin
if not CharIsWordChar(Current) then
exit;
pcToken.SourceCode := Current;
Consume;
end;
{ concat any subsequent word chars } { concat any subsequent word chars }
while CharIsWordChar(Current) or CharIsDigit(Current) do while CharIsWordChar(Current) or CharIsDigit(Current) do
@ -691,13 +716,6 @@ end;
{ ~pktb 2017.05.19 - Oct numbers are prefixed with & } { ~pktb 2017.05.19 - Oct numbers are prefixed with & }
function TBuildTokenList.TryOctNumber(const pcToken: TSourceToken): boolean; function TBuildTokenList.TryOctNumber(const pcToken: TSourceToken): boolean;
function CharIsOctDigit(const c: Char): Boolean;
const
OctDigits: set of AnsiChar = [
'0', '1', '2', '3', '4', '5', '6', '7'];
begin
Result := (c in OctDigits);
end;
begin begin
Result := False; Result := False;
@ -705,6 +723,16 @@ begin
if Current <> '&' then if Current <> '&' then
exit; exit;
//ISN'T A Octal Number.
if not CharIsOctDigit(ForwardChar(1)) then
begin
pcToken.TokenType := ttAmpersand;
pcToken.SourceCode := Current;
Consume;
result:=true;
exit;
end;
pcToken.TokenType := ttNumber; pcToken.TokenType := ttNumber;
pcToken.SourceCode := Current; pcToken.SourceCode := Current;
Consume; Consume;