界面库

抽象语法高亮类
This commit is contained in:
JianjunLiu
2022-09-15 14:27:24 +08:00
parent a89d92ad42
commit 1abe441ca6
3 changed files with 542 additions and 586 deletions
+444
View File
@@ -3014,6 +3014,450 @@ type TSynHighLighter = class(TComponent) //
Flines;
FMemo;
end
type tcustomsynhighlighter = class(TSynHighLighter)
{**
@explan(说明) 通用的语法高亮类
支持单行注释,块注释,配对,字符串定义,关键字,符号%%
@data(20220915)
**}
function create(AOwner);
begin
inherited;
fsymcolor := 0xa000a0;
fkeywordcolor := 0x0000ff;
fstringcolor := 0xff00ff;
fannotationcolor := 0xff0000;
fignorecase := false;//忽略大小写
FChangeDeal := true;
FTokens := array();
setkeyword(array("null","true","false"));
setblockannote(array(
("/*","*/"),
));
setrowannote(array("//"));
setsyms(array("+","-","*","/",";","(",")","{","}",":"));
setstring(array(
("'","\\"),
('"',"\\"),
));
setpairs(array(
("(",")"),
("{","}"),
));
clean();
end
function ExecuteCommand(cmd,pm);override;
begin
{**
@explan(说明) 对外接口 %%
@param(cmd)(string) 命令%%
@param(pm)(array) 参数 %%
**}
case cmd of
"strings":
begin
return setstring(pm);
end
"rowannotes":
begin
return setrowannote(pm);
end
"blockannotes":
begin
return setblockannote(pm);
end
"keywords":
begin
return setkeyword(pm);
end
"syms":
begin
return setsyms(pm);
end
"pairs":
begin
return setpairs(pm);
end
end ;
return inherited;
end
function SetInValidateIndex(idx);override; //当前改变的行
begin
idx := max(1,idx);
fdolastline := idx-2;
if not(FChangeDeal)and idx>FSatesCount then return;
if length(FSates)>= idx then FSatesCount := idx;
else FSatesCount := length(FSates)-1;
if FSatesCount=1 then clean();
FChangeDeal := false;
end
function InsureTokenParserd(LastLine);override; //解析
begin
ls := Lines;
FChangeDeal := true;
if fdolastline>=LastLine then return ;
fdolastline := LastLine;
for i := FSatesCount-1 to LastLine do
begin
if i<0 then continue;
s := ls.GetStringByIndex(i);
cst := FSates[i];
tks := array();
fcbgestate := array();
for jj,j in mrows(Fbgedstates,1) do
begin
v := Fbgedstates[j][i];
vj := v.Clone;
fcbgestate[j]:= vj;
Fbgedstates[j][i+1]:= vj;
end
FSates[i+1]:= ParserTokenLines(s,1,length(s),cst,tks);
FSatesCount := i+1;
FTokens[i]:= tks;
end
end
function GetLineTokens(idx);override;
begin
if idx<FSatesCount then return FTokens[idx];
end
function SetTToken(tokens,ttk,idx,ext);override; //设置token
begin
bttk := ttk;
d := inherited;
if not d then return ;
if not ext then
begin
if ifkeywords(bttk) then
begin
d.FFColor := fkeywordcolor;
end
dopair(d,bttk);
end else
if ifarray(ext) then
begin
if ext[0]="str" then
begin
d.FFColor := fstringcolor;
end else
if ext[0] = "annote" then
begin
d.FFColor := fannotationcolor;
end else
if ext[0]= "sym" then
begin
d.FFColor := fsymcolor;
dopair(d,bttk);
end
end
return d;
end
function clean();override; //初始化
begin
FTokens := array();
FSates := array(0);
Fbgedstates := array();
FSatesCount := 0;
for i,v in fswordpairs do
begin
Fbgedstates[i,0]:= new tpairstate(i);
end
inherited;
end
property keywordcolor:color read fkeywordcolor write fkeywordcolor;
property stringcolor:color read fstringcolor write fstringcolor;
property annotationcolor:color read fannotationcolor write fannotationcolor;
property symcolor:color read fsymcolor write fsymcolor;
private
function dopair(d,bttk); //处理配对信息
begin
n := fswordpairshash[bttk];
if n then
begin
st := fcbgestate[n];
if fswordpairs[n][0]=bttk then
begin
st.GetLeft();
end else
begin
st.GetRight();
end
d.FMATe := st.GetSate();
end
end
function ParserTokenLines(s,b,e,cst,tokens); //解析字符
begin
label L_XCDG;
if cst=0 then //普通情况
begin
idx := b;
ttk := "";
while idx <= e do
begin
vi := s[idx];
if vi=" " or vi="\t" then //分隔符
begin
SetTToken(tokens,ttk,idx-1);
end else
if ifrowannote(s,e,idx,oidx,ostr) then
begin
SetTToken(tokens,ttk,idx-1);
bostr := ostr;
SetTToken(tokens,ostr,oidx-1,array("annote",bostr));
if oidx<=e then
begin
SetTToken(tokens,s[oidx:],e,array("annote",bostr));
end
return 0;
end else
if ifblockannote(s,e,idx,oidx,ostr) then //查找块注释
begin
SetTToken(tokens,ttk,idx-1);
bostr := ostr;
ncost := array("annote",bostr,fblockstiresb[bostr]);
SetTToken(tokens,ostr,oidx-1);
idx := oidx-1;
return ParserTokenLines(s,idx+1,e,ncost,tokens);
end else
if ifstringstart(s,e,idx,oidx,ostr) then //查找字符串
begin
SetTToken(tokens,ttk,idx-1);
bostr := ostr;
ncost := array("str",bostr,fstrstires[bostr],fstrstires_zy[cst]);
SetTToken(tokens,ostr,oidx-1,ncost);
idx := oidx-1;
return ParserTokenLines(s,idx+1,e,ncost,tokens);
end else
if ifdefsym(s,e,idx,oidx,ostr) then //符号
begin
SetTToken(tokens,ttk,idx-1);
SetTToken(tokens,ostr,oidx-1,array("sym",ostr));
idx := oidx-1;
end else
begin
ttk+=vi;
end
idx++;
end
SetTToken(tokens,ttk,idx-1);
end else //查找
begin
if b>e then return cst;
if ifarray(cst) and (cst[0]="str" or cst[0]="annote") then
begin
cst1 := cst[1];
cstL := length(cst1);
r := FindRightChar(cst[2],s,b,e,cst[3]);
if r=0 then //没找到
begin
Setttoken(tokens,s[b:],e,cst);
return cst;
end else //找到
if r <= e then
begin
if b<r then
begin
Setttoken(tokens,s[b:r-1],r-1,cst);
end
Setttoken(tokens,s[r:(r-1+cstL)],(r-1+cstL),cst);
if r<e then
begin
//消除递归
b := r+cstL;
cst := 0;
goto L_XCDG;
//return ParserTokenLines(s,r+1,e,0,tokens); //递归方式
end
end
end
end
end
function setstring(d); //设置字符串信息
begin
fstrstires := array();
fstrstires_zy := array();
for i,v in d do
begin
if not ifarray(v) then continue;
v0 := v[0];
v1 := v[1];
if ifstring(v0) and v0 then
begin
st := new TTire();
fstrstires[v0] := st;
st.add(v0);
fstrstires_zy[v0] := v1;
end
end
end
function setkeyword(ws); //设置关键字
begin
st := new TTire();
for i,v in ws do
begin
if v and ifstring(v) then st.add(v);
end
fkeystires := array(st);
end
function setblockannote(d); //设置块注释
begin
fblockstiresa := array();
fblockstiresb := array();
for i,v in d do
begin
if not ifarray(d) then continue ;
v0 := v[0];
v1 := v[1];
if ifstring(v0) and ifstring(v1) and v0 and v1 then
begin
st := new TTire();
st.add(v0);
fblockstiresa[v0] := st;
st := new TTire();
st.add(v1);
fblockstiresb[v0] := st;
end
end
end
function setrowannote(d);//设置行注释
begin
frowstires := array();
for i,v in d do
begin
if v and ifstring(v) then
begin
st := new TTire();
frowstires[v] := st;
st.add("//");
end
end
end
function setsyms(d);//设置符号
begin
st := new TTire();
fsymstires := array(st);
for i,v in d do
begin
if ifstring(v) and v then
begin
st.add(v);
end
end
end
function setpairs(d);//设置配对
begin
fswordpairs := array();
fswordpairshash := array();
for i,v in d do
begin
if not ifarray(v) then continue;
v0 := v[0];
v1 := v[1];
if ifstring(v0) and ifstring(v1) and v0 and v1 then
begin
fswordpairs[v0,0]:= v0;
fswordpairs[v0,1]:= v1;
fswordpairshash[v0]:=v0;
fswordpairshash[v1]:=v0;
end
end
end
function cyclefind(cys,s,l,idx,oidx,ostr,tidx);
begin
r := 0;
for i,v in cys do //字符串
begin
if v.find(s,l,idx,oidx,ostr) then
begin
r := 1;
tidx := i;
break;
end
end
return r;
end
function ifblockannote(s,l,idx,oidx,ostr,tidx);//是否为块注释
begin
return cyclefind(fblockstiresa,s,l,idx,oidx,ostr,tidx);
end
function ifrowannote(s,l,idx,oidx,ostr,tidx);//是为
begin
return cyclefind(frowstires,s,l,idx,oidx,ostr,tidx);
end
function ifstringstart(s,l,idx,oidx,ostr,tidx); //字符串判断
begin
return cyclefind(fstrstires,s,l,idx,oidx,ostr,tidx);
end
function ifkeywords(s);//关键字判断
begin
for i,v in fkeystires do
begin
if v.find(s,length(s),1,idx,ostr) and (ostr=s) then
return true;
end
end
function ifdefsym(s,l,idx,oidx,ostr,tidx); //符号判断
begin
return cyclefind(fsymstires,s,l,idx,oidx,ostr,tidx);
end
function FindRightChar(vo,s,b,e,zy); //查找封闭的字符
begin
i := b;
if not vo then return 1;
while i <= e do
begin
si := s[i];
if si=zy then
begin
i += 2;
if i>e then return 0;
continue;
end
if vo.find(s,e,i,oidx,ostr) then
begin
return i;
end
i++;
end
return 0; //没找到
end
private
FSatesCount ;// 状态行号
FChangeDeal;//改变flag
fignorecase; //忽略大小写
//前后匹配
Fbgedstates;
fcbgestate;//当前匹配
///
FSates; //当前状态
FTokens;
fdolastline; //已经处理到行
///////tire树/////////////
fkeystires;
fstrstires;
fstrstires_zy;
fsymstires;
frowstires;
fblockstiresa;
fblockstiresb;
/////
fkeywordcolor;
fstringcolor;
fannotationcolor;
fsymcolor;
//
fswordpairs;
fswordpairshash;
end
type TSynCustomMemo = class(TCustomMemo)
{**
+78
View File
@@ -1695,6 +1695,84 @@ type TTire = class
end
FRoot;
end
type tpairstate =class //括号状态
function Create(t);
begin
FType := ifstring(t)?t:"";
FCJ := 0;
FState := 0;
FIndexs := array(0);
FIndex := 0;
FCstate := false;
end
function GetLeft();
begin
FCstate := true;
if FState then // 上一个是左括号
begin
FCJ++;
FIndex++;
FIndexs[FIndex]:=0;
end else //上一个非左括号
begin
FIndexs[FIndex]++;
end
FState := true;
end
function GetRight();
begin
FCstate := true;
//if FCJ=0 then return ;
if FState then // 上一个是左括号
begin
//FIndexs[FIndex]++;
end else //上一个非左括号
begin
if FCJ>0 then
begin
FCJ--;
DeleteIndex(FIndexs,FIndex);
FIndex--;
end else
begin
FCstate := false;
end
end
FState := false;
end
function GetSate();
begin
if FCstate then
begin
//return inttostr(FIndexs[FCJ])+FType;
return tostn(FIndexs)+FType;// inttostr(FCJ)+"+"+inttostr(FIndexs[FIndex])+FType; length(FIndexs)+FType ;//
end
end
function Show();
begin
echo "层级:",FCJ," 序号:",FIndexs[FIndex],"状态:", FCstate;
end
function Clone();
begin
r := new tpairstate(FType);
r.FCstate := FCstate;
r.FState := FState;
r.FCJ := FCJ;
r.FIndexs := FIndexs;
r.FIndex := FIndex;
return r;
end
protected
FCstate;
FState;
FCJ;
FIndexs;
FIndex;
FType;
end
implementation
function includestate(u,s);
begin