mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 18:28:23 +02:00
+ Implement support for parsing sets in preprocessor directives
This commit is contained in:
parent
bc72021039
commit
a31f37b5e5
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user