+ Implement support for parsing sets in preprocessor directives

This commit is contained in:
Ryan Joseph 2023-05-30 15:29:16 +02:00 committed by Sven/Sarah Barth
parent bc72021039
commit a31f37b5e5

View File

@ -28,6 +28,7 @@ interface
uses
cclasses,
globtype,globals,constexp,version,tokens,
symtype,symdef,symsym,
verbose,comphook,
finput,
widestr;
@ -253,6 +254,7 @@ interface
procedure readtoken(allowrecordtoken:boolean);
function readpreproc:ttoken;
function readpreprocint(var value:int64;const place:string):boolean;
function readpreprocset(conform_to:tsetdef;var value:tnormalset;const place:string):boolean;
function asmgetchar:char;
end;
@ -309,7 +311,7 @@ implementation
cutils,cfileutl,
systems,
switches,
symbase,symtable,symtype,symsym,symconst,symdef,defutil,
symbase,symtable,symconst,defutil,defcmp,node,
{ This is needed for tcputype }
cpuinfo,
fmodule,fppu,
@ -1022,6 +1024,7 @@ type
function asInt: Integer;
function asInt64: Int64;
function asStr: String;
function asSet: tnormalset;
destructor destroy; override;
end;
@ -1478,6 +1481,11 @@ type
result:=value.valueord.svalue;
end;
function texprvalue.asSet: tnormalset;
begin
result:=pnormalset(value.valueptr)^;
end;
function texprvalue.asStr: String;
var
b:byte;
@ -1566,7 +1574,7 @@ type
end;
function preproc_comp_expr:texprvalue;
function preproc_comp_expr(conform_to:tdef):texprvalue;
function preproc_sub_expr(pred_level:Toperator_precedence;eval:Boolean):texprvalue; forward;
@ -1821,7 +1829,8 @@ type
srsymtable : TSymtable;
hdef : TDef;
l : longint;
hasKlammer: Boolean;
hasKlammer,
read_next: Boolean;
exprvalue:texprvalue;
ns:tnormalset;
fs,path,name: tpathstr;
@ -2216,21 +2225,56 @@ type
case srsym.typ of
constsym:
begin
result.free;
result:=texprvalue.create_const(tconstsym(srsym));
tconstsym(srsym).IncRefCount;
{ const def must conform to the set type }
if (conform_to<>nil) and
(conform_to.typ=setdef) and
(tconstsym(srsym).constdef.typ=setdef) and
(compare_defs(tsetdef(tconstsym(srsym).constdef).elementdef,tsetdef(conform_to).elementdef,nothingn)<>te_exact) then
begin
result.free;
result:=nil;
// TODO(ryan): better error?
Message(scan_e_error_in_preproc_expr);
end;
if result<>nil then
begin
result.free;
result:=texprvalue.create_const(tconstsym(srsym));
tconstsym(srsym).IncRefCount;
end;
end;
enumsym:
begin
result.free;
result:=texprvalue.create_int(tenumsym(srsym).value);
tenumsym(srsym).IncRefCount;
{ enum definition must conform to the set type }
if (conform_to<>nil) and
(conform_to.typ=setdef) and
(compare_defs(tenumsym(srsym).definition,tsetdef(conform_to).elementdef,nothingn)<>te_exact) then
begin
result.free;
result:=nil;
// TODO(ryan): better error?
Message(scan_e_error_in_preproc_expr);
end;
if result<>nil then
begin
result.free;
result:=texprvalue.create_int(tenumsym(srsym).value);
tconstsym(srsym).IncRefCount;
end;
end;
else
;
end;
end
end
{ the id must be belong to the set type }
else if (conform_to<>nil) and (conform_to.typ=setdef) then
begin
result.free;
result:=nil;
// TODO(ryan): better error?
Message(scan_e_error_in_preproc_expr);
end;
end
{ skip id(<expr>) if expression must not be evaluated }
else if not(eval) and (result.consttyp=conststring) then
begin
@ -2258,16 +2302,36 @@ type
begin
preproc_consume(_LECKKLAMMER);
ns:=[];
while current_scanner.preproc_token in [_ID,_INTCONST] do
read_next:=false;
while (current_scanner.preproc_token in [_ID,_INTCONST]) or read_next do
begin
read_next:=false;
exprvalue:=preproc_factor(eval);
{ the const set does not conform to the set def }
if (conform_to<>nil) and
(conform_to.typ=setdef) and
(exprvalue.consttyp=constnone) then
begin
result:=texprvalue.create_error;
break;
end;
{ reject duplicate enums in the set }
if exprvalue.asInt in ns then
begin
Message1(sym_e_duplicate_id,current_scanner.preproc_pattern);
result:=texprvalue.create_error;
break;
end;
include(ns,exprvalue.asInt);
if current_scanner.preproc_token = _COMMA then
preproc_consume(_COMMA);
begin
preproc_consume(_COMMA);
read_next:=true;
end
end;
// TODO Add check of setElemType
preproc_consume(_RECKKLAMMER);
result:=texprvalue.create_set(ns);
if result=nil then
result:=texprvalue.create_set(ns);
end
else if current_scanner.preproc_token = _INTCONST then
begin
@ -2366,7 +2430,7 @@ type
var
hs: texprvalue;
begin
hs:=preproc_comp_expr;
hs:=preproc_comp_expr(nil);
if hs.isBoolean then
result:=hs.asBool
else
@ -2545,7 +2609,7 @@ type
if c='=' then
begin
current_scanner.readchar;
exprvalue:=preproc_comp_expr;
exprvalue:=preproc_comp_expr(nil);
if not is_boolean(exprvalue.def) and
not is_integer(exprvalue.def) then
exprvalue.error('Boolean, Integer', 'SETC');
@ -2769,7 +2833,6 @@ type
end;
end;
{*****************************************************************************
Preprocessor writing
*****************************************************************************}
@ -6080,7 +6143,7 @@ exit_label:
var
hs : texprvalue;
begin
hs:=preproc_comp_expr;
hs:=preproc_comp_expr(nil);
if hs.isInt then
begin
value:=hs.asInt64;
@ -6095,6 +6158,25 @@ exit_label:
end;
function tscannerfile.readpreprocset(conform_to:tsetdef;var value:tnormalset;const place:string):boolean;
var
hs : texprvalue;
begin
hs:=preproc_comp_expr(conform_to);
if hs.def.typ=setdef then
begin
value:=hs.asSet;
result:=true;
end
else
begin
hs.error('Set',place);
result:=false;
end;
hs.free;
end;
function tscannerfile.asmgetchar : char;
begin
readchar;