mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-01 22:10:19 +02:00
Integrated the changes from trunks's postfixoperators into my own and removed the local version again.
git-svn-id: branches/svenbarth/generics@17997 -
This commit is contained in:
parent
7a401d6f00
commit
6a60f9d42a
@ -1568,7 +1568,7 @@ implementation
|
|||||||
is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then
|
is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then
|
||||||
begin
|
begin
|
||||||
{ default property }
|
{ default property }
|
||||||
protsym:=search_default_property(tobjectdef(p1.resultdef));
|
protsym:=search_default_property(tabstractrecorddef(p1.resultdef));
|
||||||
if not(assigned(protsym)) then
|
if not(assigned(protsym)) then
|
||||||
begin
|
begin
|
||||||
p1.destroy;
|
p1.destroy;
|
||||||
@ -2298,539 +2298,6 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{---------------------------------------------
|
|
||||||
PostFixOperators
|
|
||||||
---------------------------------------------}
|
|
||||||
|
|
||||||
{ returns whether or not p1 has been changed }
|
|
||||||
function postfixoperators(var p1:tnode;var again:boolean): boolean;
|
|
||||||
|
|
||||||
{ tries to avoid syntax errors after invalid qualifiers }
|
|
||||||
procedure recoverconsume_postfixops;
|
|
||||||
begin
|
|
||||||
repeat
|
|
||||||
if not try_to_consume(_CARET) then
|
|
||||||
if try_to_consume(_POINT) then
|
|
||||||
try_to_consume(_ID)
|
|
||||||
else if try_to_consume(_LECKKLAMMER) then
|
|
||||||
begin
|
|
||||||
repeat
|
|
||||||
comp_expr(true,false);
|
|
||||||
until not try_to_consume(_COMMA);
|
|
||||||
consume(_RECKKLAMMER);
|
|
||||||
end
|
|
||||||
else if try_to_consume(_LKLAMMER) then
|
|
||||||
begin
|
|
||||||
repeat
|
|
||||||
comp_expr(true,false);
|
|
||||||
until not try_to_consume(_COMMA);
|
|
||||||
consume(_RKLAMMER);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
until false;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure handle_variantarray;
|
|
||||||
var
|
|
||||||
p4 : tnode;
|
|
||||||
newstatement : tstatementnode;
|
|
||||||
tempresultvariant,
|
|
||||||
temp : ttempcreatenode;
|
|
||||||
paras : tcallparanode;
|
|
||||||
newblock : tnode;
|
|
||||||
countindices : aint;
|
|
||||||
begin
|
|
||||||
{ create statements with call initialize the arguments and
|
|
||||||
call fpc_dynarr_setlength }
|
|
||||||
newblock:=internalstatements(newstatement);
|
|
||||||
|
|
||||||
{ get temp for array of indicies,
|
|
||||||
we set the real size later }
|
|
||||||
temp:=ctempcreatenode.create(s32inttype,4,tt_persistent,false);
|
|
||||||
addstatement(newstatement,temp);
|
|
||||||
|
|
||||||
countindices:=0;
|
|
||||||
repeat
|
|
||||||
p4:=comp_expr(true,false);
|
|
||||||
|
|
||||||
addstatement(newstatement,cassignmentnode.create(
|
|
||||||
ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4));
|
|
||||||
inc(countindices);
|
|
||||||
until not try_to_consume(_COMMA);
|
|
||||||
|
|
||||||
{ set real size }
|
|
||||||
temp.size:=countindices*s32inttype.size;
|
|
||||||
|
|
||||||
consume(_RECKKLAMMER);
|
|
||||||
|
|
||||||
{ we need only a write access if a := follows }
|
|
||||||
if token=_ASSIGNMENT then
|
|
||||||
begin
|
|
||||||
consume(_ASSIGNMENT);
|
|
||||||
p4:=comp_expr(true,false);
|
|
||||||
|
|
||||||
{ create call to fpc_vararray_put }
|
|
||||||
paras:=ccallparanode.create(cordconstnode.create
|
|
||||||
(countindices,s32inttype,true),
|
|
||||||
ccallparanode.create(caddrnode.create_internal
|
|
||||||
(ctemprefnode.create(temp)),
|
|
||||||
ccallparanode.create(ctypeconvnode.create_internal(p4,cvarianttype),
|
|
||||||
ccallparanode.create(ctypeconvnode.create_internal(p1,cvarianttype)
|
|
||||||
,nil))));
|
|
||||||
|
|
||||||
addstatement(newstatement,ccallnode.createintern('fpc_vararray_put',paras));
|
|
||||||
addstatement(newstatement,ctempdeletenode.create(temp));
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ create temp for result }
|
|
||||||
tempresultvariant:=ctempcreatenode.create(cvarianttype,cvarianttype.size,tt_persistent,true);
|
|
||||||
addstatement(newstatement,tempresultvariant);
|
|
||||||
|
|
||||||
{ create call to fpc_vararray_get }
|
|
||||||
paras:=ccallparanode.create(cordconstnode.create
|
|
||||||
(countindices,s32inttype,true),
|
|
||||||
ccallparanode.create(caddrnode.create_internal
|
|
||||||
(ctemprefnode.create(temp)),
|
|
||||||
ccallparanode.create(p1,
|
|
||||||
ccallparanode.create(
|
|
||||||
ctemprefnode.create(tempresultvariant)
|
|
||||||
,nil))));
|
|
||||||
|
|
||||||
addstatement(newstatement,ccallnode.createintern('fpc_vararray_get',paras));
|
|
||||||
addstatement(newstatement,ctempdeletenode.create(temp));
|
|
||||||
{ the last statement should return the value as
|
|
||||||
location and type, this is done be referencing the
|
|
||||||
temp and converting it first from a persistent temp to
|
|
||||||
normal temp }
|
|
||||||
addstatement(newstatement,ctempdeletenode.create_normal_temp(tempresultvariant));
|
|
||||||
addstatement(newstatement,ctemprefnode.create(tempresultvariant));
|
|
||||||
end;
|
|
||||||
p1:=newblock;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
protsym : tpropertysym;
|
|
||||||
p2,p3 : tnode;
|
|
||||||
srsym : tsym;
|
|
||||||
srsymtable : TSymtable;
|
|
||||||
structh : tabstractrecorddef;
|
|
||||||
{ shouldn't be used that often, so the extra overhead is ok to save
|
|
||||||
stack space }
|
|
||||||
dispatchstring : ansistring;
|
|
||||||
nodechanged : boolean;
|
|
||||||
calltype: tdispcalltype;
|
|
||||||
label
|
|
||||||
skipreckklammercheck;
|
|
||||||
begin
|
|
||||||
result:=false;
|
|
||||||
again:=true;
|
|
||||||
while again do
|
|
||||||
begin
|
|
||||||
{ we need the resultdef }
|
|
||||||
do_typecheckpass_changed(p1,nodechanged);
|
|
||||||
result:=result or nodechanged;
|
|
||||||
|
|
||||||
if codegenerror then
|
|
||||||
begin
|
|
||||||
recoverconsume_postfixops;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{ handle token }
|
|
||||||
case token of
|
|
||||||
_CARET:
|
|
||||||
begin
|
|
||||||
consume(_CARET);
|
|
||||||
|
|
||||||
{ support tp/mac procvar^ if the procvar returns a
|
|
||||||
pointer type }
|
|
||||||
if ((m_tp_procvar in current_settings.modeswitches) or
|
|
||||||
(m_mac_procvar in current_settings.modeswitches)) and
|
|
||||||
(p1.resultdef.typ=procvardef) and
|
|
||||||
(tprocvardef(p1.resultdef).returndef.typ=pointerdef) then
|
|
||||||
begin
|
|
||||||
p1:=ccallnode.create_procvar(nil,p1);
|
|
||||||
typecheckpass(p1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (p1.resultdef.typ<>pointerdef) then
|
|
||||||
begin
|
|
||||||
{ ^ as binary operator is a problem!!!! (FK) }
|
|
||||||
again:=false;
|
|
||||||
Message(parser_e_invalid_qualifier);
|
|
||||||
recoverconsume_postfixops;
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
p1:=cderefnode.create(p1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
_LECKKLAMMER:
|
|
||||||
begin
|
|
||||||
if is_class_or_interface_or_object(p1.resultdef) or
|
|
||||||
is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then
|
|
||||||
begin
|
|
||||||
{ default property }
|
|
||||||
protsym:=search_default_property(tabstractrecorddef(p1.resultdef));
|
|
||||||
if not(assigned(protsym)) then
|
|
||||||
begin
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
again:=false;
|
|
||||||
message(parser_e_no_default_property_available);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ The property symbol is referenced indirect }
|
|
||||||
protsym.IncRefCount;
|
|
||||||
handle_propertysym(protsym,protsym.owner,p1);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
consume(_LECKKLAMMER);
|
|
||||||
repeat
|
|
||||||
{ in all of the cases below, p1 is changed }
|
|
||||||
case p1.resultdef.typ of
|
|
||||||
pointerdef:
|
|
||||||
begin
|
|
||||||
{ support delphi autoderef }
|
|
||||||
if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and
|
|
||||||
(m_autoderef in current_settings.modeswitches) then
|
|
||||||
p1:=cderefnode.create(p1);
|
|
||||||
p2:=comp_expr(true,false);
|
|
||||||
{ Support Pbytevar[0..9] which returns array [0..9].}
|
|
||||||
if try_to_consume(_POINTPOINT) then
|
|
||||||
p2:=crangenode.create(p2,comp_expr(true,false));
|
|
||||||
p1:=cvecnode.create(p1,p2);
|
|
||||||
end;
|
|
||||||
variantdef:
|
|
||||||
begin
|
|
||||||
handle_variantarray;
|
|
||||||
{ the RECKKLAMMER is already read }
|
|
||||||
goto skipreckklammercheck;
|
|
||||||
end;
|
|
||||||
stringdef :
|
|
||||||
begin
|
|
||||||
p2:=comp_expr(true,false);
|
|
||||||
{ Support string[0..9] which returns array [0..9] of char.}
|
|
||||||
if try_to_consume(_POINTPOINT) then
|
|
||||||
p2:=crangenode.create(p2,comp_expr(true,false));
|
|
||||||
p1:=cvecnode.create(p1,p2);
|
|
||||||
end;
|
|
||||||
arraydef:
|
|
||||||
begin
|
|
||||||
p2:=comp_expr(true,false);
|
|
||||||
{ support SEG:OFS for go32v2 Mem[] }
|
|
||||||
if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
|
|
||||||
(p1.nodetype=loadn) and
|
|
||||||
assigned(tloadnode(p1).symtableentry) and
|
|
||||||
assigned(tloadnode(p1).symtableentry.owner.name) and
|
|
||||||
(tloadnode(p1).symtableentry.owner.name^='SYSTEM') and
|
|
||||||
((tloadnode(p1).symtableentry.name='MEM') or
|
|
||||||
(tloadnode(p1).symtableentry.name='MEMW') or
|
|
||||||
(tloadnode(p1).symtableentry.name='MEML')) then
|
|
||||||
begin
|
|
||||||
if try_to_consume(_COLON) then
|
|
||||||
begin
|
|
||||||
p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
|
|
||||||
p2:=comp_expr(true,false);
|
|
||||||
p2:=caddnode.create(addn,p2,p3);
|
|
||||||
if try_to_consume(_POINTPOINT) then
|
|
||||||
{ Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.}
|
|
||||||
p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,false),p3.getcopy));
|
|
||||||
p1:=cvecnode.create(p1,p2);
|
|
||||||
include(tvecnode(p1).flags,nf_memseg);
|
|
||||||
include(tvecnode(p1).flags,nf_memindex);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if try_to_consume(_POINTPOINT) then
|
|
||||||
{ Support mem[$80000000..$80000002] which returns array [0..2] of memtype.}
|
|
||||||
p2:=crangenode.create(p2,comp_expr(true,false));
|
|
||||||
p1:=cvecnode.create(p1,p2);
|
|
||||||
include(tvecnode(p1).flags,nf_memindex);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if try_to_consume(_POINTPOINT) then
|
|
||||||
{ Support arrayvar[0..9] which returns array [0..9] of arraytype.}
|
|
||||||
p2:=crangenode.create(p2,comp_expr(true,false));
|
|
||||||
p1:=cvecnode.create(p1,p2);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if p1.resultdef.typ<>undefineddef then
|
|
||||||
Message(parser_e_invalid_qualifier);
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
comp_expr(true,false);
|
|
||||||
again:=false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
do_typecheckpass(p1);
|
|
||||||
until not try_to_consume(_COMMA);
|
|
||||||
consume(_RECKKLAMMER);
|
|
||||||
{ handle_variantarray eats the RECKKLAMMER and jumps here }
|
|
||||||
skipreckklammercheck:
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
_POINT :
|
|
||||||
begin
|
|
||||||
consume(_POINT);
|
|
||||||
if (p1.resultdef.typ=pointerdef) and
|
|
||||||
(m_autoderef in current_settings.modeswitches) and
|
|
||||||
{ don't auto-deref objc.id, because then the code
|
|
||||||
below for supporting id.anyobjcmethod isn't triggered }
|
|
||||||
(p1.resultdef<>objc_idtype) then
|
|
||||||
begin
|
|
||||||
p1:=cderefnode.create(p1);
|
|
||||||
do_typecheckpass(p1);
|
|
||||||
end;
|
|
||||||
{ procvar.<something> can never mean anything so always
|
|
||||||
try to call it in case it returns a record/object/... }
|
|
||||||
maybe_call_procvar(p1,false);
|
|
||||||
|
|
||||||
case p1.resultdef.typ of
|
|
||||||
recorddef:
|
|
||||||
begin
|
|
||||||
if token=_ID then
|
|
||||||
begin
|
|
||||||
structh:=tabstractrecorddef(p1.resultdef);
|
|
||||||
searchsym_in_record(structh,pattern,srsym,srsymtable);
|
|
||||||
if assigned(srsym) then
|
|
||||||
begin
|
|
||||||
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
||||||
consume(_ID);
|
|
||||||
do_member_read(structh,getaddr,srsym,p1,again,[]);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Message1(sym_e_id_no_member,orgpattern);
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
{ try to clean up }
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
enumdef:
|
|
||||||
begin
|
|
||||||
if token=_ID then
|
|
||||||
begin
|
|
||||||
srsym:=tsym(tenumdef(p1.resultdef).symtable.Find(pattern));
|
|
||||||
p1.destroy;
|
|
||||||
if assigned(srsym) and (srsym.typ=enumsym) then
|
|
||||||
begin
|
|
||||||
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
||||||
p1:=genenumnode(tenumsym(srsym));
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Message1(sym_e_id_no_member,orgpattern);
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
variantdef:
|
|
||||||
begin
|
|
||||||
{ dispatch call? }
|
|
||||||
{ lhs := v.ident[parameters] -> property get
|
|
||||||
lhs := v.ident(parameters) -> method call
|
|
||||||
v.ident[parameters] := rhs -> property put
|
|
||||||
v.ident(parameters) := rhs -> also property put }
|
|
||||||
if token=_ID then
|
|
||||||
begin
|
|
||||||
dispatchstring:=orgpattern;
|
|
||||||
consume(_ID);
|
|
||||||
calltype:=dct_method;
|
|
||||||
if try_to_consume(_LKLAMMER) then
|
|
||||||
begin
|
|
||||||
p2:=parse_paras(false,true,_RKLAMMER);
|
|
||||||
consume(_RKLAMMER);
|
|
||||||
end
|
|
||||||
else if try_to_consume(_LECKKLAMMER) then
|
|
||||||
begin
|
|
||||||
p2:=parse_paras(false,true,_RECKKLAMMER);
|
|
||||||
consume(_RECKKLAMMER);
|
|
||||||
calltype:=dct_propget;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
p2:=nil;
|
|
||||||
{ property setter? }
|
|
||||||
if (token=_ASSIGNMENT) and not(afterassignment) then
|
|
||||||
begin
|
|
||||||
consume(_ASSIGNMENT);
|
|
||||||
{ read the expression }
|
|
||||||
p3:=comp_expr(true,false);
|
|
||||||
{ concat value parameter too }
|
|
||||||
p2:=ccallparanode.create(p3,p2);
|
|
||||||
p1:=translate_disp_call(p1,p2,dct_propput,dispatchstring,0,voidtype);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
{ this is only an approximation
|
|
||||||
setting useresult if not necessary is only a waste of time, no more, no less (FK) }
|
|
||||||
if afterassignment or in_args or (token<>_SEMICOLON) then
|
|
||||||
p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,cvarianttype)
|
|
||||||
else
|
|
||||||
p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,voidtype);
|
|
||||||
end
|
|
||||||
else { Error }
|
|
||||||
Consume(_ID);
|
|
||||||
end;
|
|
||||||
classrefdef:
|
|
||||||
begin
|
|
||||||
if token=_ID then
|
|
||||||
begin
|
|
||||||
structh:=tobjectdef(tclassrefdef(p1.resultdef).pointeddef);
|
|
||||||
searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true);
|
|
||||||
if assigned(srsym) then
|
|
||||||
begin
|
|
||||||
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
||||||
consume(_ID);
|
|
||||||
do_member_read(structh,getaddr,srsym,p1,again,[]);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Message1(sym_e_id_no_member,orgpattern);
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
{ try to clean up }
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else { Error }
|
|
||||||
Consume(_ID);
|
|
||||||
end;
|
|
||||||
objectdef:
|
|
||||||
begin
|
|
||||||
if token=_ID then
|
|
||||||
begin
|
|
||||||
structh:=tobjectdef(p1.resultdef);
|
|
||||||
searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true);
|
|
||||||
if assigned(srsym) then
|
|
||||||
begin
|
|
||||||
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
||||||
consume(_ID);
|
|
||||||
do_member_read(structh,getaddr,srsym,p1,again,[]);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Message1(sym_e_id_no_member,orgpattern);
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
{ try to clean up }
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else { Error }
|
|
||||||
Consume(_ID);
|
|
||||||
end;
|
|
||||||
pointerdef:
|
|
||||||
begin
|
|
||||||
if (p1.resultdef=objc_idtype) then
|
|
||||||
begin
|
|
||||||
{ objc's id type can be used to call any
|
|
||||||
Objective-C method of any Objective-C class
|
|
||||||
type that's currently in scope }
|
|
||||||
if search_objc_method(pattern,srsym,srsymtable) then
|
|
||||||
begin
|
|
||||||
consume(_ID);
|
|
||||||
do_proc_call(srsym,srsymtable,nil,
|
|
||||||
(getaddr and not(token in [_CARET,_POINT])),
|
|
||||||
again,p1,[cnf_objc_id_call]);
|
|
||||||
{ we need to know which procedure is called }
|
|
||||||
do_typecheckpass(p1);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
consume(_ID);
|
|
||||||
Message(parser_e_methode_id_expected);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Message(parser_e_invalid_qualifier);
|
|
||||||
if tpointerdef(p1.resultdef).pointeddef.typ in [recorddef,objectdef,classrefdef] then
|
|
||||||
Message(parser_h_maybe_deref_caret_missing);
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if p1.resultdef.typ<>undefineddef then
|
|
||||||
Message(parser_e_invalid_qualifier);
|
|
||||||
p1.destroy;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
{ Error }
|
|
||||||
consume(_ID);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ is this a procedure variable ? }
|
|
||||||
if assigned(p1.resultdef) and
|
|
||||||
(p1.resultdef.typ=procvardef) then
|
|
||||||
begin
|
|
||||||
{ Typenode for typecasting or expecting a procvar }
|
|
||||||
if (p1.nodetype=typen) or
|
|
||||||
(
|
|
||||||
assigned(getprocvardef) and
|
|
||||||
equal_defs(p1.resultdef,getprocvardef)
|
|
||||||
) then
|
|
||||||
begin
|
|
||||||
if try_to_consume(_LKLAMMER) then
|
|
||||||
begin
|
|
||||||
p1:=comp_expr(true,false);
|
|
||||||
consume(_RKLAMMER);
|
|
||||||
p1:=ctypeconvnode.create_explicit(p1,p1.resultdef);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
again:=false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if try_to_consume(_LKLAMMER) then
|
|
||||||
begin
|
|
||||||
p2:=parse_paras(false,false,_RKLAMMER);
|
|
||||||
consume(_RKLAMMER);
|
|
||||||
p1:=ccallnode.create_procvar(p2,p1);
|
|
||||||
{ proc():= is never possible }
|
|
||||||
if token=_ASSIGNMENT then
|
|
||||||
begin
|
|
||||||
Message(parser_e_illegal_expression);
|
|
||||||
p1.free;
|
|
||||||
p1:=cerrornode.create;
|
|
||||||
again:=false;
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
again:=false;
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
again:=false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ we only try again if p1 was changed }
|
|
||||||
if again or
|
|
||||||
(p1.nodetype=errorn) then
|
|
||||||
result:=true;
|
|
||||||
end; { while again }
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{---------------------------------------------
|
{---------------------------------------------
|
||||||
Factor (Main)
|
Factor (Main)
|
||||||
---------------------------------------------}
|
---------------------------------------------}
|
||||||
|
Loading…
Reference in New Issue
Block a user