pexpr.pas 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Does parsing of expression for Free Pascal
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pexpr;
  19. interface
  20. uses symtable,tree;
  21. { reads a whole expression }
  22. function expr : ptree;
  23. { reads an expression without assignements and .. }
  24. function comp_expr(accept_equal : boolean):Ptree;
  25. { reads a single factor }
  26. function factor(getaddr : boolean) : ptree;
  27. { the ID token has to be consumed before calling this function }
  28. procedure do_member_read(getaddr : boolean;const sym : psym;var p1 : ptree;
  29. var pd : pdef;var again : boolean);
  30. function get_intconst:longint;
  31. function get_stringconst:string;
  32. implementation
  33. uses
  34. globtype,systems,tokens,
  35. cobjects,globals,scanner,
  36. symconst,aasm,htypechk,
  37. {$ifdef newcg}
  38. cgbase,
  39. {$else}
  40. hcodegen,
  41. {$endif}
  42. types,verbose,strings,
  43. {$ifndef newcg}
  44. tccal,
  45. {$endif newcg}
  46. pass_1,
  47. { parser specific stuff }
  48. pbase,ptype,
  49. { processor specific stuff }
  50. cpubase,cpuinfo;
  51. { sub_expr(opmultiply) is need to get -1 ** 4 to be
  52. read as - (1**4) and not (-1)**4 PM }
  53. type
  54. Toperator_precedence=(opcompare,opaddition,opmultiply,oppower);
  55. const
  56. highest_precedence = oppower;
  57. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;forward;
  58. const
  59. allow_type : boolean = true;
  60. got_addrn : boolean = false;
  61. auto_inherited : boolean = false;
  62. function parse_paras(__colon,in_prop_paras : boolean) : ptree;
  63. var
  64. p1,p2 : ptree;
  65. end_of_paras : ttoken;
  66. begin
  67. if in_prop_paras then
  68. end_of_paras:=_RECKKLAMMER
  69. else
  70. end_of_paras:=_RKLAMMER;
  71. if token=end_of_paras then
  72. begin
  73. parse_paras:=nil;
  74. exit;
  75. end;
  76. p2:=nil;
  77. inc(parsing_para_level);
  78. while true do
  79. begin
  80. p1:=comp_expr(true);
  81. p2:=gencallparanode(p1,p2);
  82. { it's for the str(l:5,s); }
  83. if __colon and (token=_COLON) then
  84. begin
  85. consume(_COLON);
  86. p1:=comp_expr(true);
  87. p2:=gencallparanode(p1,p2);
  88. p2^.is_colon_para:=true;
  89. if token=_COLON then
  90. begin
  91. consume(_COLON);
  92. p1:=comp_expr(true);
  93. p2:=gencallparanode(p1,p2);
  94. p2^.is_colon_para:=true;
  95. end
  96. end;
  97. if token=_COMMA then
  98. consume(_COMMA)
  99. else
  100. break;
  101. end;
  102. dec(parsing_para_level);
  103. parse_paras:=p2;
  104. end;
  105. procedure check_tp_procvar(var p : ptree);
  106. var
  107. p1 : ptree;
  108. begin
  109. if (m_tp_procvar in aktmodeswitches) and
  110. (not got_addrn) and
  111. (not in_args) and
  112. (p^.treetype=loadn) then
  113. begin
  114. { support if procvar then for tp7 and many other expression like this }
  115. do_firstpass(p);
  116. set_varstate(p,false);
  117. { reset varstateset to maybe set used state later web bug769 PM }
  118. unset_varstate(p);
  119. if not(getprocvar) and (p^.resulttype^.deftype=procvardef) then
  120. begin
  121. p1:=gencallnode(nil,nil);
  122. p1^.right:=p;
  123. p1^.resulttype:=pprocvardef(p^.resulttype)^.rettype.def;
  124. firstpass(p1);
  125. p:=p1;
  126. end;
  127. end;
  128. end;
  129. function statement_syssym(l : longint;var pd : pdef) : ptree;
  130. var
  131. p1,p2,paras : ptree;
  132. prev_in_args : boolean;
  133. begin
  134. prev_in_args:=in_args;
  135. case l of
  136. in_ord_x :
  137. begin
  138. consume(_LKLAMMER);
  139. in_args:=true;
  140. p1:=comp_expr(true);
  141. consume(_RKLAMMER);
  142. do_firstpass(p1);
  143. p1:=geninlinenode(in_ord_x,false,p1);
  144. do_firstpass(p1);
  145. statement_syssym := p1;
  146. pd:=p1^.resulttype;
  147. end;
  148. in_break :
  149. begin
  150. statement_syssym:=genzeronode(breakn);
  151. pd:=voiddef;
  152. end;
  153. in_continue :
  154. begin
  155. statement_syssym:=genzeronode(continuen);
  156. pd:=voiddef;
  157. end;
  158. in_typeof_x :
  159. begin
  160. consume(_LKLAMMER);
  161. in_args:=true;
  162. {allow_type:=true;}
  163. p1:=comp_expr(true);
  164. {allow_type:=false;}
  165. consume(_RKLAMMER);
  166. pd:=voidpointerdef;
  167. if p1^.treetype=typen then
  168. begin
  169. if (p1^.typenodetype=nil) then
  170. begin
  171. Message(type_e_mismatch);
  172. statement_syssym:=genzeronode(errorn);
  173. end
  174. else
  175. if p1^.typenodetype^.deftype=objectdef then
  176. begin
  177. { we can use resulttype in pass_2 (PM) }
  178. p1^.resulttype:=p1^.typenodetype;
  179. statement_syssym:=geninlinenode(in_typeof_x,false,p1);
  180. end
  181. else
  182. begin
  183. Message(type_e_mismatch);
  184. disposetree(p1);
  185. statement_syssym:=genzeronode(errorn);
  186. end;
  187. end
  188. else { not a type node }
  189. begin
  190. do_firstpass(p1);
  191. set_varstate(p1,false);
  192. if (p1^.resulttype=nil) then
  193. begin
  194. Message(type_e_mismatch);
  195. disposetree(p1);
  196. statement_syssym:=genzeronode(errorn)
  197. end
  198. else
  199. if p1^.resulttype^.deftype=objectdef then
  200. statement_syssym:=geninlinenode(in_typeof_x,false,p1)
  201. else
  202. begin
  203. Message(type_e_mismatch);
  204. statement_syssym:=genzeronode(errorn);
  205. disposetree(p1);
  206. end;
  207. end;
  208. end;
  209. in_sizeof_x :
  210. begin
  211. consume(_LKLAMMER);
  212. in_args:=true;
  213. {allow_type:=true;}
  214. p1:=comp_expr(true);
  215. {allow_type:=false; }
  216. consume(_RKLAMMER);
  217. pd:=s32bitdef;
  218. if p1^.treetype=typen then
  219. begin
  220. statement_syssym:=genordinalconstnode(p1^.typenodetype^.size,pd);
  221. { p1 not needed !}
  222. disposetree(p1);
  223. end
  224. else
  225. begin
  226. do_firstpass(p1);
  227. if ((p1^.resulttype^.deftype=objectdef) and
  228. (oo_has_constructor in pobjectdef(p1^.resulttype)^.objectoptions)) or
  229. is_open_array(p1^.resulttype) or
  230. is_open_string(p1^.resulttype) then
  231. statement_syssym:=geninlinenode(in_sizeof_x,false,p1)
  232. else
  233. begin
  234. statement_syssym:=genordinalconstnode(p1^.resulttype^.size,pd);
  235. { p1 not needed !}
  236. disposetree(p1);
  237. end;
  238. end;
  239. end;
  240. in_assigned_x :
  241. begin
  242. consume(_LKLAMMER);
  243. in_args:=true;
  244. p1:=comp_expr(true);
  245. do_firstpass(p1);
  246. if not codegenerror then
  247. begin
  248. case p1^.resulttype^.deftype of
  249. pointerdef,
  250. procvardef,
  251. classrefdef : ;
  252. objectdef :
  253. if not(pobjectdef(p1^.resulttype)^.is_class) then
  254. Message(parser_e_illegal_parameter_list);
  255. else
  256. Message(parser_e_illegal_parameter_list);
  257. end;
  258. end;
  259. p2:=gencallparanode(p1,nil);
  260. p2:=geninlinenode(in_assigned_x,false,p2);
  261. consume(_RKLAMMER);
  262. pd:=booldef;
  263. statement_syssym:=p2;
  264. end;
  265. in_ofs_x :
  266. begin
  267. consume(_LKLAMMER);
  268. in_args:=true;
  269. p1:=comp_expr(true);
  270. p1:=gensinglenode(addrn,p1);
  271. do_firstpass(p1);
  272. { Ofs() returns a longint, not a pointer }
  273. p1^.resulttype:=u32bitdef;
  274. pd:=p1^.resulttype;
  275. consume(_RKLAMMER);
  276. statement_syssym:=p1;
  277. end;
  278. in_addr_x :
  279. begin
  280. consume(_LKLAMMER);
  281. in_args:=true;
  282. p1:=comp_expr(true);
  283. p1:=gensinglenode(addrn,p1);
  284. do_firstpass(p1);
  285. pd:=p1^.resulttype;
  286. consume(_RKLAMMER);
  287. statement_syssym:=p1;
  288. end;
  289. in_seg_x :
  290. begin
  291. consume(_LKLAMMER);
  292. in_args:=true;
  293. p1:=comp_expr(true);
  294. do_firstpass(p1);
  295. set_varstate(p1,false);
  296. if p1^.location.loc<>LOC_REFERENCE then
  297. Message(cg_e_illegal_expression);
  298. p1:=genordinalconstnode(0,s32bitdef);
  299. pd:=s32bitdef;
  300. consume(_RKLAMMER);
  301. statement_syssym:=p1;
  302. end;
  303. in_high_x,
  304. in_low_x :
  305. begin
  306. consume(_LKLAMMER);
  307. in_args:=true;
  308. {allow_type:=true;}
  309. p1:=comp_expr(true);
  310. {allow_type:=false;}
  311. do_firstpass(p1);
  312. if p1^.treetype=typen then
  313. p1^.resulttype:=p1^.typenodetype;
  314. p2:=geninlinenode(l,false,p1);
  315. consume(_RKLAMMER);
  316. pd:=s32bitdef;
  317. statement_syssym:=p2;
  318. end;
  319. in_succ_x,
  320. in_pred_x :
  321. begin
  322. consume(_LKLAMMER);
  323. in_args:=true;
  324. p1:=comp_expr(true);
  325. do_firstpass(p1);
  326. p2:=geninlinenode(l,false,p1);
  327. consume(_RKLAMMER);
  328. pd:=p1^.resulttype;
  329. statement_syssym:=p2;
  330. end;
  331. in_inc_x,
  332. in_dec_x :
  333. begin
  334. consume(_LKLAMMER);
  335. in_args:=true;
  336. p1:=comp_expr(true);
  337. if token=_COMMA then
  338. begin
  339. consume(_COMMA);
  340. p2:=gencallparanode(comp_expr(true),nil);
  341. end
  342. else
  343. p2:=nil;
  344. p2:=gencallparanode(p1,p2);
  345. statement_syssym:=geninlinenode(l,false,p2);
  346. consume(_RKLAMMER);
  347. pd:=voiddef;
  348. end;
  349. in_concat_x :
  350. begin
  351. consume(_LKLAMMER);
  352. in_args:=true;
  353. p2:=nil;
  354. while true do
  355. begin
  356. p1:=comp_expr(true);
  357. do_firstpass(p1);
  358. set_varstate(p1,true);
  359. if not((p1^.resulttype^.deftype=stringdef) or
  360. ((p1^.resulttype^.deftype=orddef) and
  361. (porddef(p1^.resulttype)^.typ=uchar))) then
  362. Message(parser_e_illegal_parameter_list);
  363. if p2<>nil then
  364. p2:=gennode(addn,p2,p1)
  365. else
  366. p2:=p1;
  367. if token=_COMMA then
  368. consume(_COMMA)
  369. else
  370. break;
  371. end;
  372. consume(_RKLAMMER);
  373. pd:=cshortstringdef;
  374. statement_syssym:=p2;
  375. end;
  376. in_read_x,
  377. in_readln_x :
  378. begin
  379. if token=_LKLAMMER then
  380. begin
  381. consume(_LKLAMMER);
  382. in_args:=true;
  383. paras:=parse_paras(false,false);
  384. consume(_RKLAMMER);
  385. end
  386. else
  387. paras:=nil;
  388. pd:=voiddef;
  389. p1:=geninlinenode(l,false,paras);
  390. do_firstpass(p1);
  391. statement_syssym := p1;
  392. end;
  393. in_write_x,
  394. in_writeln_x :
  395. begin
  396. if token=_LKLAMMER then
  397. begin
  398. consume(_LKLAMMER);
  399. in_args:=true;
  400. paras:=parse_paras(true,false);
  401. consume(_RKLAMMER);
  402. end
  403. else
  404. paras:=nil;
  405. pd:=voiddef;
  406. p1 := geninlinenode(l,false,paras);
  407. do_firstpass(p1);
  408. statement_syssym := p1;
  409. end;
  410. in_str_x_string :
  411. begin
  412. consume(_LKLAMMER);
  413. in_args:=true;
  414. paras:=parse_paras(true,false);
  415. consume(_RKLAMMER);
  416. p1 := geninlinenode(l,false,paras);
  417. do_firstpass(p1);
  418. statement_syssym := p1;
  419. pd:=voiddef;
  420. end;
  421. in_val_x:
  422. Begin
  423. consume(_LKLAMMER);
  424. in_args := true;
  425. p1:= gencallparanode(comp_expr(true), nil);
  426. consume(_COMMA);
  427. p2 := gencallparanode(comp_expr(true),p1);
  428. if (token = _COMMA) then
  429. Begin
  430. consume(_COMMA);
  431. p2 := gencallparanode(comp_expr(true),p2)
  432. End;
  433. consume(_RKLAMMER);
  434. p2 := geninlinenode(l,false,p2);
  435. do_firstpass(p2);
  436. statement_syssym := p2;
  437. pd := voiddef;
  438. End;
  439. in_include_x_y,
  440. in_exclude_x_y :
  441. begin
  442. consume(_LKLAMMER);
  443. in_args:=true;
  444. p1:=comp_expr(true);
  445. consume(_COMMA);
  446. p2:=comp_expr(true);
  447. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  448. consume(_RKLAMMER);
  449. pd:=voiddef;
  450. end;
  451. in_assert_x_y :
  452. begin
  453. consume(_LKLAMMER);
  454. in_args:=true;
  455. p1:=comp_expr(true);
  456. if token=_COMMA then
  457. begin
  458. consume(_COMMA);
  459. p2:=comp_expr(true);
  460. end
  461. else
  462. begin
  463. { then insert an empty string }
  464. p2:=genstringconstnode('',st_default);
  465. end;
  466. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  467. consume(_RKLAMMER);
  468. pd:=voiddef;
  469. end;
  470. else
  471. internalerror(15);
  472. end;
  473. in_args:=prev_in_args;
  474. end;
  475. { reads the parameter for a subroutine call }
  476. procedure do_proc_call(getaddr : boolean;var again : boolean;var p1:Ptree;var pd:Pdef);
  477. var
  478. prev_in_args : boolean;
  479. prevafterassn : boolean;
  480. hs,hs1 : pvarsym;
  481. st : psymtable;
  482. p2 : ptree;
  483. begin
  484. prev_in_args:=in_args;
  485. prevafterassn:=afterassignment;
  486. afterassignment:=false;
  487. { want we only determine the address of }
  488. { a subroutine ? }
  489. if not(getaddr) then
  490. begin
  491. if auto_inherited then
  492. begin
  493. st:=symtablestack;
  494. while assigned(st) and (st^.symtabletype<>parasymtable) do
  495. st:=st^.next;
  496. p2:=nil;
  497. if assigned(st) then
  498. begin
  499. hs:=pvarsym(st^.symindex^.first);
  500. while assigned(hs) do
  501. begin
  502. if hs^.typ<>varsym then
  503. internalerror(54382953);
  504. { if there is a localcopy then use that }
  505. if assigned(hs^.localvarsym) then
  506. hs1:=hs^.localvarsym
  507. else
  508. hs1:=hs;
  509. p2:=gencallparanode(genloadnode(hs1,hs1^.owner),p2);
  510. hs:=pvarsym(hs^.next);
  511. end;
  512. end
  513. else
  514. internalerror(54382954);
  515. p1^.left:=p2;
  516. end
  517. else
  518. begin
  519. if token=_LKLAMMER then
  520. begin
  521. consume(_LKLAMMER);
  522. in_args:=true;
  523. p1^.left:=parse_paras(false,false);
  524. consume(_RKLAMMER);
  525. end
  526. else
  527. p1^.left:=nil;
  528. end;
  529. { do firstpass because we need the }
  530. { result type }
  531. do_firstpass(p1);
  532. {set_var_state is handled inside firstcalln }
  533. end
  534. else
  535. begin
  536. { address operator @: }
  537. p1^.left:=nil;
  538. { forget pd }
  539. pd:=nil;
  540. if (p1^.symtableproc^.symtabletype=withsymtable) and
  541. (p1^.symtableproc^.defowner^.deftype=objectdef) then
  542. begin
  543. p1^.methodpointer:=getcopy(pwithsymtable(p1^.symtableproc)^.withrefnode);
  544. end
  545. else if not(assigned(p1^.methodpointer)) then
  546. begin
  547. { we must provide a method pointer, if it isn't given, }
  548. { it is self }
  549. if assigned(procinfo) then
  550. begin
  551. p1^.methodpointer:=genselfnode(procinfo^._class);
  552. p1^.methodpointer^.resulttype:=procinfo^._class;
  553. end
  554. else
  555. begin
  556. p1^.methodpointer:=genselfnode(nil);
  557. p1^.methodpointer^.resulttype:=nil;
  558. end;
  559. end;
  560. { no postfix operators }
  561. again:=false;
  562. end;
  563. pd:=p1^.resulttype;
  564. in_args:=prev_in_args;
  565. afterassignment:=prevafterassn;
  566. end;
  567. procedure handle_procvar(pv : pprocvardef;var p2 : ptree);
  568. procedure doconv(procvar : pprocvardef;var t : ptree);
  569. var
  570. hp : ptree;
  571. begin
  572. hp:=nil;
  573. if (proc_to_procvar_equal(pprocsym(t^.symtableentry)^.definition,procvar)) then
  574. begin
  575. if (po_methodpointer in procvar^.procoptions) then
  576. hp:=genloadmethodcallnode(pprocsym(t^.symtableprocentry),t^.symtable,getcopy(t^.methodpointer))
  577. else
  578. hp:=genloadcallnode(pprocsym(t^.symtableprocentry),t^.symtable);
  579. end;
  580. if assigned(hp) then
  581. begin
  582. disposetree(t);
  583. t:=hp;
  584. end;
  585. end;
  586. begin
  587. if (p2^.treetype=calln) then
  588. doconv(pv,p2)
  589. else
  590. if (p2^.treetype=typeconvn) and
  591. (p2^.left^.treetype=calln) then
  592. doconv(pv,p2^.left);
  593. end;
  594. { the following procedure handles the access to a property symbol }
  595. procedure handle_propertysym(sym : psym;st : psymtable;var p1 : ptree;
  596. var pd : pdef);
  597. var
  598. paras : ptree;
  599. p2 : ptree;
  600. plist : psymlistitem;
  601. begin
  602. paras:=nil;
  603. { property parameters? read them only if the property really }
  604. { has parameters }
  605. if ppo_hasparameters in ppropertysym(sym)^.propoptions then
  606. begin
  607. if token=_LECKKLAMMER then
  608. begin
  609. consume(_LECKKLAMMER);
  610. paras:=parse_paras(false,true);
  611. consume(_RECKKLAMMER);
  612. end;
  613. { indexed property }
  614. if (ppo_indexed in ppropertysym(sym)^.propoptions) then
  615. begin
  616. p2:=genordinalconstnode(ppropertysym(sym)^.index,ppropertysym(sym)^.indextype.def);
  617. paras:=gencallparanode(p2,paras);
  618. end;
  619. end;
  620. { we need only a write property if a := follows }
  621. { if not(afterassignment) and not(in_args) then }
  622. if token=_ASSIGNMENT then
  623. begin
  624. { write property: }
  625. { no result }
  626. pd:=voiddef;
  627. if not ppropertysym(sym)^.writeaccess^.empty then
  628. begin
  629. case ppropertysym(sym)^.writeaccess^.firstsym^.sym^.typ of
  630. procsym :
  631. begin
  632. { generate the method call }
  633. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.writeaccess^.firstsym^.sym),st,p1);
  634. { we know the procedure to call, so
  635. force the usage of that procedure }
  636. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.writeaccess^.def);
  637. p1^.left:=paras;
  638. consume(_ASSIGNMENT);
  639. { read the expression }
  640. getprocvar:=ppropertysym(sym)^.proptype.def^.deftype=procvardef;
  641. p2:=comp_expr(true);
  642. if getprocvar then
  643. handle_procvar(pprocvardef(ppropertysym(sym)^.proptype.def),p2);
  644. p1^.left:=gencallparanode(p2,p1^.left);
  645. p1^.isproperty:=true;
  646. getprocvar:=false;
  647. end;
  648. varsym :
  649. begin
  650. if assigned(paras) then
  651. message(parser_e_no_paras_allowed);
  652. { subscribed access? }
  653. plist:=ppropertysym(sym)^.writeaccess^.firstsym;
  654. while assigned(plist) do
  655. begin
  656. if p1=nil then
  657. p1:=genloadnode(pvarsym(plist^.sym),st)
  658. else
  659. p1:=gensubscriptnode(pvarsym(plist^.sym),p1);
  660. plist:=plist^.next;
  661. end;
  662. p1^.isproperty:=true;
  663. consume(_ASSIGNMENT);
  664. { read the expression }
  665. p2:=comp_expr(true);
  666. p1:=gennode(assignn,p1,p2);
  667. end
  668. else
  669. begin
  670. p1:=genzeronode(errorn);
  671. Message(parser_e_no_procedure_to_access_property);
  672. end;
  673. end;
  674. end
  675. else
  676. begin
  677. p1:=genzeronode(errorn);
  678. Message(parser_e_no_procedure_to_access_property);
  679. end;
  680. end
  681. else
  682. begin
  683. { read property: }
  684. pd:=ppropertysym(sym)^.proptype.def;
  685. if not ppropertysym(sym)^.readaccess^.empty then
  686. begin
  687. case ppropertysym(sym)^.readaccess^.firstsym^.sym^.typ of
  688. varsym :
  689. begin
  690. if assigned(paras) then
  691. message(parser_e_no_paras_allowed);
  692. { subscribed access? }
  693. plist:=ppropertysym(sym)^.readaccess^.firstsym;
  694. while assigned(plist) do
  695. begin
  696. if p1=nil then
  697. p1:=genloadnode(pvarsym(plist^.sym),st)
  698. else
  699. p1:=gensubscriptnode(pvarsym(plist^.sym),p1);
  700. plist:=plist^.next;
  701. end;
  702. p1^.isproperty:=true;
  703. end;
  704. procsym :
  705. begin
  706. { generate the method call }
  707. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.readaccess^.firstsym^.sym),st,p1);
  708. { we know the procedure to call, so
  709. force the usage of that procedure }
  710. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.readaccess^.def);
  711. { insert paras }
  712. p1^.left:=paras;
  713. p1^.isproperty:=true;
  714. end
  715. else
  716. begin
  717. p1:=genzeronode(errorn);
  718. Message(type_e_mismatch);
  719. end;
  720. end;
  721. end
  722. else
  723. begin
  724. { error, no function to read property }
  725. p1:=genzeronode(errorn);
  726. Message(parser_e_no_procedure_to_access_property);
  727. end;
  728. end;
  729. end;
  730. { the ID token has to be consumed before calling this function }
  731. procedure do_member_read(getaddr : boolean;const sym : psym;var p1 : ptree;
  732. var pd : pdef;var again : boolean);
  733. var
  734. static_name : string;
  735. isclassref : boolean;
  736. objdef : pobjectdef;
  737. begin
  738. if sym=nil then
  739. begin
  740. { pattern is still valid unless
  741. there is another ID just after the ID of sym }
  742. Message1(sym_e_id_no_member,pattern);
  743. disposetree(p1);
  744. p1:=genzeronode(errorn);
  745. { try to clean up }
  746. pd:=generrordef;
  747. again:=false;
  748. end
  749. else
  750. begin
  751. objdef:=pobjectdef(sym^.owner^.defowner);
  752. isclassref:=(pd^.deftype=classrefdef);
  753. { check protected and private members }
  754. { please leave this code as it is, }
  755. { it has now the same behaviaor as TP/Delphi }
  756. if (sp_private in sym^.symoptions) and
  757. (objdef^.owner^.symtabletype=unitsymtable) then
  758. Message(parser_e_cant_access_private_member);
  759. if (sp_protected in sym^.symoptions) and
  760. (objdef^.owner^.symtabletype=unitsymtable) then
  761. begin
  762. if assigned(aktprocsym^.definition^._class) then
  763. begin
  764. if not aktprocsym^.definition^._class^.is_related(objdef) then
  765. Message(parser_e_cant_access_protected_member);
  766. end
  767. else
  768. Message(parser_e_cant_access_protected_member);
  769. end;
  770. { we assume, that only procsyms and varsyms are in an object }
  771. { symbol table, for classes, properties are allowed }
  772. case sym^.typ of
  773. procsym:
  774. begin
  775. p1:=genmethodcallnode(pprocsym(sym),sym^.owner,p1);
  776. do_proc_call(getaddr or
  777. (getprocvar and
  778. ((block_type=bt_const) or
  779. ((m_tp_procvar in aktmodeswitches) and
  780. proc_to_procvar_equal(pprocsym(sym)^.definition,getprocvardef)
  781. )
  782. )
  783. ),again,p1,pd);
  784. if (block_type=bt_const) and
  785. getprocvar then
  786. handle_procvar(getprocvardef,p1);
  787. { now we know the real method e.g. we can check for a class method }
  788. if isclassref and
  789. assigned(p1^.procdefinition) and
  790. not(po_classmethod in p1^.procdefinition^.procoptions) and
  791. not(p1^.procdefinition^.proctypeoption=potype_constructor) then
  792. Message(parser_e_only_class_methods_via_class_ref);
  793. end;
  794. varsym:
  795. begin
  796. if isclassref then
  797. Message(parser_e_only_class_methods_via_class_ref);
  798. if (sp_static in sym^.symoptions) then
  799. begin
  800. { static_name:=lower(srsymtable^.name^)+'_'+sym^.name;
  801. this is wrong for static field in with symtable (PM) }
  802. static_name:=lower(srsym^.owner^.name^)+'_'+sym^.name;
  803. getsym(static_name,true);
  804. disposetree(p1);
  805. p1:=genloadnode(pvarsym(srsym),srsymtable);
  806. end
  807. else
  808. p1:=gensubscriptnode(pvarsym(sym),p1);
  809. pd:=pvarsym(sym)^.vartype.def;
  810. end;
  811. propertysym:
  812. begin
  813. if isclassref then
  814. Message(parser_e_only_class_methods_via_class_ref);
  815. handle_propertysym(sym,srsymtable,p1,pd);
  816. end;
  817. else internalerror(16);
  818. end;
  819. end;
  820. end;
  821. {****************************************************************************
  822. Factor
  823. ****************************************************************************}
  824. {$ifdef fpc}
  825. {$maxfpuregisters 0}
  826. {$endif fpc}
  827. function factor(getaddr : boolean) : ptree;
  828. var
  829. l : longint;
  830. oldp1,
  831. p1,p2,p3 : ptree;
  832. code : integer;
  833. pd,pd2 : pdef;
  834. possible_error,
  835. unit_specific,
  836. again : boolean;
  837. sym : psym;
  838. classh : pobjectdef;
  839. d : bestreal;
  840. hs,
  841. static_name : string;
  842. propsym : ppropertysym;
  843. filepos : tfileposinfo;
  844. {---------------------------------------------
  845. Is_func_ret
  846. ---------------------------------------------}
  847. function is_func_ret(sym : psym) : boolean;
  848. var
  849. p : pprocinfo;
  850. storesymtablestack : psymtable;
  851. begin
  852. is_func_ret:=false;
  853. if not assigned(procinfo) or
  854. ((sym^.typ<>funcretsym) and ((procinfo^.flags and pi_operator)=0)) then
  855. exit;
  856. p:=procinfo;
  857. while assigned(p) do
  858. begin
  859. { is this an access to a function result? Accessing _RESULT is
  860. always allowed and funcretn is generated }
  861. if assigned(p^.funcretsym) and
  862. ((pfuncretsym(sym)=p^.resultfuncretsym) or
  863. ((pfuncretsym(sym)=p^.funcretsym) or
  864. ((pvarsym(sym)=opsym) and ((p^.flags and pi_operator)<>0))) and
  865. (p^.returntype.def<>pdef(voiddef)) and
  866. (token<>_LKLAMMER) and
  867. (not ((m_tp in aktmodeswitches) and (afterassignment or in_args)))
  868. ) then
  869. begin
  870. if ((pvarsym(sym)=opsym) and
  871. ((p^.flags and pi_operator)<>0)) then
  872. inc(opsym^.refs);
  873. p1:=genzeronode(funcretn);
  874. pd:=p^.returntype.def;
  875. p1^.funcretprocinfo:=p;
  876. p1^.rettype.def:=pd;
  877. is_func_ret:=true;
  878. if p^.funcret_state=vs_declared then
  879. begin
  880. p^.funcret_state:=vs_declared_and_first_found;
  881. p1^.is_first_funcret:=true;
  882. end;
  883. exit;
  884. end;
  885. p:=p^.parent;
  886. end;
  887. { we must use the function call }
  888. if (sym^.typ=funcretsym) then
  889. begin
  890. storesymtablestack:=symtablestack;
  891. symtablestack:=srsymtable^.next;
  892. getsym(sym^.name,true);
  893. if srsym^.typ<>procsym then
  894. Message(cg_e_illegal_expression);
  895. symtablestack:=storesymtablestack;
  896. end;
  897. end;
  898. {---------------------------------------------
  899. Factor_read_id
  900. ---------------------------------------------}
  901. procedure factor_read_id;
  902. var
  903. pc : pchar;
  904. len : longint;
  905. begin
  906. { allow post fix operators }
  907. again:=true;
  908. begin
  909. if lastsymknown then
  910. begin
  911. srsym:=lastsrsym;
  912. srsymtable:=lastsrsymtable;
  913. lastsymknown:=false;
  914. end
  915. else
  916. getsym(pattern,true);
  917. consume(_ID);
  918. if not is_func_ret(srsym) then
  919. { else it's a normal symbol }
  920. begin
  921. { is it defined like UNIT.SYMBOL ? }
  922. if srsym^.typ=unitsym then
  923. begin
  924. consume(_POINT);
  925. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  926. unit_specific:=true;
  927. consume(_ID);
  928. end
  929. else
  930. unit_specific:=false;
  931. if not assigned(srsym) then
  932. Begin
  933. p1:=genzeronode(errorn);
  934. { try to clean up }
  935. pd:=generrordef;
  936. end
  937. else
  938. Begin
  939. { check semantics of private }
  940. if (srsym^.typ in [propertysym,procsym,varsym]) and
  941. (srsymtable^.symtabletype=objectsymtable) then
  942. begin
  943. if (sp_private in srsym^.symoptions) and
  944. (pobjectdef(srsym^.owner^.defowner)^.owner^.symtabletype=unitsymtable) then
  945. Message(parser_e_cant_access_private_member);
  946. end;
  947. case srsym^.typ of
  948. absolutesym : begin
  949. p1:=genloadnode(pvarsym(srsym),srsymtable);
  950. pd:=pabsolutesym(srsym)^.vartype.def;
  951. end;
  952. varsym : begin
  953. { are we in a class method ? }
  954. if (srsymtable^.symtabletype=objectsymtable) and
  955. assigned(aktprocsym) and
  956. (po_classmethod in aktprocsym^.definition^.procoptions) then
  957. Message(parser_e_only_class_methods);
  958. if (sp_static in srsym^.symoptions) then
  959. begin
  960. static_name:=lower(srsym^.owner^.name^)+'_'+srsym^.name;
  961. getsym(static_name,true);
  962. end;
  963. p1:=genloadnode(pvarsym(srsym),srsymtable);
  964. if pvarsym(srsym)^.varstate=vs_declared then
  965. begin
  966. p1^.is_first := true;
  967. { set special between first loaded until checked in firstpass }
  968. pvarsym(srsym)^.varstate:=vs_declared_and_first_found;
  969. end;
  970. pd:=pvarsym(srsym)^.vartype.def;
  971. end;
  972. typedconstsym : begin
  973. p1:=gentypedconstloadnode(ptypedconstsym(srsym),srsymtable);
  974. pd:=ptypedconstsym(srsym)^.typedconsttype.def;
  975. end;
  976. syssym : p1:=statement_syssym(psyssym(srsym)^.number,pd);
  977. typesym : begin
  978. pd:=ptypesym(srsym)^.restype.def;
  979. if not assigned(pd) then
  980. begin
  981. pd:=generrordef;
  982. again:=false;
  983. end
  984. else
  985. begin
  986. { if we read a type declaration }
  987. { we have to return the type and }
  988. { nothing else }
  989. if block_type=bt_type then
  990. begin
  991. { we don't need sym reference when it's in the
  992. current unit or system unit, because those
  993. units are always loaded (PFV) }
  994. if not(assigned(pd^.owner)) or
  995. (pd^.owner^.unitid=0) or
  996. (pd^.owner^.unitid=1) then
  997. p1:=gentypenode(pd,nil)
  998. else
  999. p1:=gentypenode(pd,ptypesym(srsym));
  1000. { here we can also set resulttype !! }
  1001. p1^.resulttype:=pd;
  1002. pd:=voiddef;
  1003. end
  1004. else { not type block }
  1005. begin
  1006. if token=_LKLAMMER then
  1007. begin
  1008. consume(_LKLAMMER);
  1009. p1:=comp_expr(true);
  1010. consume(_RKLAMMER);
  1011. p1:=gentypeconvnode(p1,pd);
  1012. p1^.explizit:=true;
  1013. end
  1014. else { not LKLAMMER}
  1015. if (token=_POINT) and
  1016. (pd^.deftype=objectdef) and
  1017. not(pobjectdef(pd)^.is_class) then
  1018. begin
  1019. consume(_POINT);
  1020. if assigned(procinfo) and
  1021. assigned(procinfo^._class) and
  1022. not(getaddr) then
  1023. begin
  1024. if procinfo^._class^.is_related(pobjectdef(pd)) then
  1025. begin
  1026. p1:=gentypenode(pd,ptypesym(srsym));
  1027. p1^.resulttype:=pd;
  1028. { search also in inherited methods }
  1029. repeat
  1030. srsymtable:=pobjectdef(pd)^.symtable;
  1031. sym:=pvarsym(srsymtable^.search(pattern));
  1032. if assigned(sym) then
  1033. break;
  1034. pd:=pobjectdef(pd)^.childof;
  1035. until not assigned(pd);
  1036. consume(_ID);
  1037. do_member_read(false,sym,p1,pd,again);
  1038. end
  1039. else
  1040. begin
  1041. Message(parser_e_no_super_class);
  1042. pd:=generrordef;
  1043. again:=false;
  1044. end;
  1045. end
  1046. else
  1047. begin
  1048. { allows @TObject.Load }
  1049. { also allows static methods and variables }
  1050. p1:=genzeronode(typen);
  1051. p1^.resulttype:=pd;
  1052. { TP allows also @TMenu.Load if Load is only }
  1053. { defined in an anchestor class }
  1054. sym:=pvarsym(search_class_member(pobjectdef(pd),pattern));
  1055. if not assigned(sym) then
  1056. Message1(sym_e_id_no_member,pattern)
  1057. else if not(getaddr) and not(sp_static in sym^.symoptions) then
  1058. Message(sym_e_only_static_in_static)
  1059. else
  1060. begin
  1061. consume(_ID);
  1062. do_member_read(getaddr,sym,p1,pd,again);
  1063. end;
  1064. end;
  1065. end
  1066. else
  1067. begin
  1068. { class reference ? }
  1069. if (pd^.deftype=objectdef)
  1070. and pobjectdef(pd)^.is_class then
  1071. begin
  1072. p1:=gentypenode(pd,nil);
  1073. p1^.resulttype:=pd;
  1074. pd:=new(pclassrefdef,init(pd));
  1075. p1:=gensinglenode(loadvmtn,p1);
  1076. p1^.resulttype:=pd;
  1077. end
  1078. else
  1079. begin
  1080. { generate a type node }
  1081. { (for typeof etc) }
  1082. if allow_type then
  1083. begin
  1084. p1:=gentypenode(pd,nil);
  1085. { here we must use typenodetype explicitly !! PM
  1086. p1^.resulttype:=pd; }
  1087. pd:=voiddef;
  1088. end
  1089. else
  1090. Message(parser_e_no_type_not_allowed_here);
  1091. end;
  1092. end;
  1093. end;
  1094. end;
  1095. end;
  1096. enumsym : begin
  1097. p1:=genenumnode(penumsym(srsym));
  1098. pd:=p1^.resulttype;
  1099. end;
  1100. constsym : begin
  1101. case pconstsym(srsym)^.consttyp of
  1102. constint :
  1103. p1:=genordinalconstnode(pconstsym(srsym)^.value,s32bitdef);
  1104. conststring :
  1105. begin
  1106. len:=pconstsym(srsym)^.len;
  1107. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1108. len:=255;
  1109. getmem(pc,len+1);
  1110. move(pchar(pconstsym(srsym)^.value)^,pc^,len);
  1111. pc[len]:=#0;
  1112. p1:=genpcharconstnode(pc,len);
  1113. end;
  1114. constchar :
  1115. p1:=genordinalconstnode(pconstsym(srsym)^.value,cchardef);
  1116. constreal :
  1117. p1:=genrealconstnode(pbestreal(pconstsym(srsym)^.value)^,bestrealdef^);
  1118. constbool :
  1119. p1:=genordinalconstnode(pconstsym(srsym)^.value,booldef);
  1120. constset :
  1121. p1:=gensetconstnode(pconstset(pconstsym(srsym)^.value),
  1122. psetdef(pconstsym(srsym)^.consttype.def));
  1123. constord :
  1124. p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1125. pconstsym(srsym)^.consttype.def);
  1126. constpointer :
  1127. p1:=genpointerconstnode(pconstsym(srsym)^.value,
  1128. pconstsym(srsym)^.consttype.def);
  1129. constnil :
  1130. p1:=genzeronode(niln);
  1131. constresourcestring:
  1132. begin
  1133. p1:=genloadnode(pvarsym(srsym),srsymtable);
  1134. p1^.resulttype:=cansistringdef;
  1135. end;
  1136. end;
  1137. pd:=p1^.resulttype;
  1138. end;
  1139. procsym : begin
  1140. { are we in a class method ? }
  1141. possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1142. assigned(aktprocsym) and
  1143. (po_classmethod in aktprocsym^.definition^.procoptions);
  1144. p1:=gencallnode(pprocsym(srsym),srsymtable);
  1145. p1^.unit_specific:=unit_specific;
  1146. do_proc_call(getaddr or
  1147. (getprocvar and
  1148. ((block_type=bt_const) or
  1149. ((m_tp_procvar in aktmodeswitches) and
  1150. proc_to_procvar_equal(pprocsym(srsym)^.definition,getprocvardef)
  1151. )
  1152. )
  1153. ),again,p1,pd);
  1154. if (block_type=bt_const) and
  1155. getprocvar then
  1156. handle_procvar(getprocvardef,p1);
  1157. if possible_error and
  1158. not(po_classmethod in p1^.procdefinition^.procoptions) then
  1159. Message(parser_e_only_class_methods);
  1160. end;
  1161. propertysym : begin
  1162. { access to property in a method }
  1163. { are we in a class method ? }
  1164. if (srsymtable^.symtabletype=objectsymtable) and
  1165. assigned(aktprocsym) and
  1166. (po_classmethod in aktprocsym^.definition^.procoptions) then
  1167. Message(parser_e_only_class_methods);
  1168. { no method pointer }
  1169. p1:=nil;
  1170. handle_propertysym(srsym,srsymtable,p1,pd);
  1171. end;
  1172. errorsym : begin
  1173. p1:=genzeronode(errorn);
  1174. p1^.resulttype:=generrordef;
  1175. pd:=generrordef;
  1176. if token=_LKLAMMER then
  1177. begin
  1178. consume(_LKLAMMER);
  1179. parse_paras(false,false);
  1180. consume(_RKLAMMER);
  1181. end;
  1182. end;
  1183. else
  1184. begin
  1185. p1:=genzeronode(errorn);
  1186. pd:=generrordef;
  1187. Message(cg_e_illegal_expression);
  1188. end;
  1189. end; { end case }
  1190. end;
  1191. end;
  1192. end;
  1193. end;
  1194. {---------------------------------------------
  1195. Factor_Read_Set
  1196. ---------------------------------------------}
  1197. { Read a set between [] }
  1198. function factor_read_set:ptree;
  1199. var
  1200. p1,
  1201. lastp,
  1202. buildp : ptree;
  1203. begin
  1204. buildp:=nil;
  1205. { be sure that a least one arrayconstructn is used, also for an
  1206. empty [] }
  1207. if token=_RECKKLAMMER then
  1208. buildp:=gennode(arrayconstructn,nil,buildp)
  1209. else
  1210. begin
  1211. while true do
  1212. begin
  1213. p1:=comp_expr(true);
  1214. if token=_POINTPOINT then
  1215. begin
  1216. consume(_POINTPOINT);
  1217. p2:=comp_expr(true);
  1218. p1:=gennode(arrayconstructrangen,p1,p2);
  1219. end;
  1220. { insert at the end of the tree, to get the correct order }
  1221. if not assigned(buildp) then
  1222. begin
  1223. buildp:=gennode(arrayconstructn,p1,nil);
  1224. lastp:=buildp;
  1225. end
  1226. else
  1227. begin
  1228. lastp^.right:=gennode(arrayconstructn,p1,nil);
  1229. lastp:=lastp^.right;
  1230. end;
  1231. { there could be more elements }
  1232. if token=_COMMA then
  1233. consume(_COMMA)
  1234. else
  1235. break;
  1236. end;
  1237. end;
  1238. factor_read_set:=buildp;
  1239. end;
  1240. {---------------------------------------------
  1241. Helpers
  1242. ---------------------------------------------}
  1243. procedure check_tokenpos;
  1244. begin
  1245. if (p1<>oldp1) then
  1246. begin
  1247. if assigned(p1) then
  1248. set_tree_filepos(p1,filepos);
  1249. oldp1:=p1;
  1250. filepos:=tokenpos;
  1251. end;
  1252. end;
  1253. {---------------------------------------------
  1254. PostFixOperators
  1255. ---------------------------------------------}
  1256. procedure postfixoperators;
  1257. var
  1258. store_static : boolean;
  1259. { p1 and p2 must contain valid value_str }
  1260. begin
  1261. check_tokenpos;
  1262. while again do
  1263. begin
  1264. { prevent crashes with unknown types }
  1265. if not assigned(pd) then
  1266. begin
  1267. { try to recover }
  1268. repeat
  1269. case token of
  1270. _CARET:
  1271. consume(_CARET);
  1272. _POINT:
  1273. begin
  1274. consume(_POINT);
  1275. consume(_ID);
  1276. end;
  1277. _LECKKLAMMER:
  1278. begin
  1279. repeat
  1280. consume(token);
  1281. until token in [_RECKKLAMMER,_SEMICOLON];
  1282. end;
  1283. else
  1284. break;
  1285. end;
  1286. until false;
  1287. exit;
  1288. end;
  1289. { handle token }
  1290. case token of
  1291. _CARET:
  1292. begin
  1293. consume(_CARET);
  1294. if (pd^.deftype<>pointerdef) then
  1295. begin
  1296. { ^ as binary operator is a problem!!!! (FK) }
  1297. again:=false;
  1298. Message(cg_e_invalid_qualifier);
  1299. disposetree(p1);
  1300. p1:=genzeronode(errorn);
  1301. end
  1302. else
  1303. begin
  1304. p1:=gensinglenode(derefn,p1);
  1305. pd:=ppointerdef(pd)^.pointertype.def;
  1306. end;
  1307. end;
  1308. _LECKKLAMMER:
  1309. begin
  1310. if (pd^.deftype=objectdef) and pobjectdef(pd)^.is_class then
  1311. begin
  1312. { default property }
  1313. propsym:=search_default_property(pobjectdef(pd));
  1314. if not(assigned(propsym)) then
  1315. begin
  1316. disposetree(p1);
  1317. p1:=genzeronode(errorn);
  1318. again:=false;
  1319. message(parser_e_no_default_property_available);
  1320. end
  1321. else
  1322. handle_propertysym(propsym,propsym^.owner,p1,pd);
  1323. end
  1324. else
  1325. begin
  1326. consume(_LECKKLAMMER);
  1327. repeat
  1328. case pd^.deftype of
  1329. pointerdef:
  1330. begin
  1331. p2:=comp_expr(true);
  1332. p1:=gennode(vecn,p1,p2);
  1333. pd:=ppointerdef(pd)^.pointertype.def;
  1334. end;
  1335. stringdef : begin
  1336. p2:=comp_expr(true);
  1337. p1:=gennode(vecn,p1,p2);
  1338. pd:=cchardef
  1339. end;
  1340. arraydef : begin
  1341. p2:=comp_expr(true);
  1342. { support SEG:OFS for go32v2 Mem[] }
  1343. if (target_info.target=target_i386_go32v2) and
  1344. (p1^.treetype=loadn) and
  1345. assigned(p1^.symtableentry) and
  1346. assigned(p1^.symtableentry^.owner^.name) and
  1347. (p1^.symtableentry^.owner^.name^='SYSTEM') and
  1348. ((p1^.symtableentry^.name='MEM') or
  1349. (p1^.symtableentry^.name='MEMW') or
  1350. (p1^.symtableentry^.name='MEML')) then
  1351. begin
  1352. if (token=_COLON) then
  1353. begin
  1354. consume(_COLON);
  1355. p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  1356. p2:=comp_expr(true);
  1357. p2:=gennode(addn,p2,p3);
  1358. p1:=gennode(vecn,p1,p2);
  1359. p1^.memseg:=true;
  1360. p1^.memindex:=true;
  1361. end
  1362. else
  1363. begin
  1364. p1:=gennode(vecn,p1,p2);
  1365. p1^.memindex:=true;
  1366. end;
  1367. end
  1368. else
  1369. p1:=gennode(vecn,p1,p2);
  1370. pd:=parraydef(pd)^.elementtype.def;
  1371. end;
  1372. else
  1373. begin
  1374. Message(cg_e_invalid_qualifier);
  1375. disposetree(p1);
  1376. p1:=genzeronode(errorn);
  1377. again:=false;
  1378. end;
  1379. end;
  1380. if token=_COMMA then
  1381. consume(_COMMA)
  1382. else
  1383. break;
  1384. until false;
  1385. consume(_RECKKLAMMER);
  1386. end;
  1387. end;
  1388. _POINT : begin
  1389. consume(_POINT);
  1390. if (pd^.deftype=pointerdef) and
  1391. (m_autoderef in aktmodeswitches) then
  1392. begin
  1393. p1:=gensinglenode(derefn,p1);
  1394. pd:=ppointerdef(pd)^.pointertype.def;
  1395. end;
  1396. case pd^.deftype of
  1397. recorddef:
  1398. begin
  1399. sym:=precorddef(pd)^.symtable^.search(pattern);
  1400. if assigned(sym) and
  1401. (sym^.typ=varsym) then
  1402. begin
  1403. p1:=gensubscriptnode(pvarsym(sym),p1);
  1404. pd:=pvarsym(sym)^.vartype.def;
  1405. end
  1406. else
  1407. begin
  1408. Message1(sym_e_illegal_field,pattern);
  1409. disposetree(p1);
  1410. p1:=genzeronode(errorn);
  1411. end;
  1412. consume(_ID);
  1413. end;
  1414. classrefdef:
  1415. begin
  1416. classh:=pobjectdef(pclassrefdef(pd)^.pointertype.def);
  1417. sym:=nil;
  1418. while assigned(classh) do
  1419. begin
  1420. sym:=classh^.symtable^.search(pattern);
  1421. srsymtable:=classh^.symtable;
  1422. if assigned(sym) then
  1423. break;
  1424. classh:=classh^.childof;
  1425. end;
  1426. if sym=nil then
  1427. begin
  1428. Message1(sym_e_id_no_member,pattern);
  1429. disposetree(p1);
  1430. p1:=genzeronode(errorn);
  1431. { try to clean up }
  1432. pd:=generrordef;
  1433. consume(_ID);
  1434. end
  1435. else
  1436. begin
  1437. consume(_ID);
  1438. do_member_read(getaddr,sym,p1,pd,again);
  1439. end;
  1440. end;
  1441. objectdef:
  1442. begin
  1443. classh:=pobjectdef(pd);
  1444. sym:=nil;
  1445. store_static:=allow_only_static;
  1446. allow_only_static:=false;
  1447. while assigned(classh) do
  1448. begin
  1449. sym:=classh^.symtable^.search(pattern);
  1450. srsymtable:=classh^.symtable;
  1451. if assigned(sym) then
  1452. break;
  1453. classh:=classh^.childof;
  1454. end;
  1455. allow_only_static:=store_static;
  1456. if sym=nil then
  1457. begin
  1458. Message1(sym_e_id_no_member,pattern);
  1459. disposetree(p1);
  1460. p1:=genzeronode(errorn);
  1461. { try to clean up }
  1462. pd:=generrordef;
  1463. consume(_ID);
  1464. end
  1465. else
  1466. begin
  1467. consume(_ID);
  1468. do_member_read(getaddr,sym,p1,pd,again);
  1469. end;
  1470. end;
  1471. pointerdef:
  1472. begin
  1473. Message(cg_e_invalid_qualifier);
  1474. if ppointerdef(pd)^.pointertype.def^.deftype in [recorddef,objectdef,classrefdef] then
  1475. Message(parser_h_maybe_deref_caret_missing);
  1476. end;
  1477. else
  1478. begin
  1479. Message(cg_e_invalid_qualifier);
  1480. disposetree(p1);
  1481. p1:=genzeronode(errorn);
  1482. end;
  1483. end;
  1484. end;
  1485. else
  1486. begin
  1487. { is this a procedure variable ? }
  1488. if assigned(pd) then
  1489. begin
  1490. if (pd^.deftype=procvardef) then
  1491. begin
  1492. if getprocvar and is_equal(pd,getprocvardef) then
  1493. again:=false
  1494. else
  1495. if (token=_LKLAMMER) or
  1496. ((pprocvardef(pd)^.para^.empty) and
  1497. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1498. (not afterassignment) and
  1499. (not in_args)) then
  1500. begin
  1501. { do this in a strange way }
  1502. { it's not a clean solution }
  1503. p2:=p1;
  1504. p1:=gencallnode(nil,nil);
  1505. p1^.right:=p2;
  1506. p1^.unit_specific:=unit_specific;
  1507. p1^.symtableprocentry:=pprocsym(sym);
  1508. if token=_LKLAMMER then
  1509. begin
  1510. consume(_LKLAMMER);
  1511. p1^.left:=parse_paras(false,false);
  1512. consume(_RKLAMMER);
  1513. end;
  1514. pd:=pprocvardef(pd)^.rettype.def;
  1515. { proc():= is never possible }
  1516. if token=_ASSIGNMENT then
  1517. begin
  1518. Message(cg_e_illegal_expression);
  1519. p1:=genzeronode(errorn);
  1520. again:=false;
  1521. end;
  1522. p1^.resulttype:=pd;
  1523. end
  1524. else
  1525. again:=false;
  1526. p1^.resulttype:=pd;
  1527. end
  1528. else
  1529. again:=false;
  1530. end
  1531. else
  1532. again:=false;
  1533. end;
  1534. end;
  1535. check_tokenpos;
  1536. end; { while again }
  1537. end;
  1538. {---------------------------------------------
  1539. Factor (Main)
  1540. ---------------------------------------------}
  1541. begin
  1542. oldp1:=nil;
  1543. p1:=nil;
  1544. filepos:=tokenpos;
  1545. if token=_ID then
  1546. begin
  1547. factor_read_id;
  1548. { handle post fix operators }
  1549. postfixoperators;
  1550. end
  1551. else
  1552. case token of
  1553. _NEW : begin
  1554. consume(_NEW);
  1555. consume(_LKLAMMER);
  1556. {allow_type:=true;}
  1557. p1:=factor(false);
  1558. {allow_type:=false;}
  1559. if p1^.treetype<>typen then
  1560. begin
  1561. Message(type_e_type_id_expected);
  1562. disposetree(p1);
  1563. pd:=generrordef;
  1564. end
  1565. else
  1566. pd:=p1^.typenodetype;
  1567. pd2:=pd;
  1568. if (pd^.deftype<>pointerdef) then
  1569. Message1(type_e_pointer_type_expected,pd^.typename)
  1570. else
  1571. if token=_RKLAMMER then
  1572. begin
  1573. if (ppointerdef(pd)^.pointertype.def^.deftype=objectdef) and
  1574. (oo_has_vmt in pobjectdef(ppointerdef(pd)^.pointertype.def)^.objectoptions) then
  1575. Message(parser_w_use_extended_syntax_for_objects);
  1576. p1:=gensinglenode(newn,nil);
  1577. p1^.resulttype:=pd2;
  1578. consume(_RKLAMMER);
  1579. end
  1580. else
  1581. begin
  1582. disposetree(p1);
  1583. p1:=genzeronode(hnewn);
  1584. p1^.resulttype:=ppointerdef(pd)^.pointertype.def;
  1585. consume(_COMMA);
  1586. afterassignment:=false;
  1587. { determines the current object defintion }
  1588. classh:=pobjectdef(ppointerdef(pd)^.pointertype.def);
  1589. if classh^.deftype<>objectdef then
  1590. Message(parser_e_pointer_to_class_expected)
  1591. else
  1592. begin
  1593. { check for an abstract class }
  1594. if (oo_has_abstract in classh^.objectoptions) then
  1595. Message(sym_e_no_instance_of_abstract_object);
  1596. { search the constructor also in the symbol tables of
  1597. the parents }
  1598. sym:=nil;
  1599. while assigned(classh) do
  1600. begin
  1601. sym:=classh^.symtable^.search(pattern);
  1602. srsymtable:=classh^.symtable;
  1603. if assigned(sym) then
  1604. break;
  1605. classh:=classh^.childof;
  1606. end;
  1607. consume(_ID);
  1608. do_member_read(false,sym,p1,pd,again);
  1609. if (p1^.treetype<>calln) or
  1610. (assigned(p1^.procdefinition) and
  1611. (p1^.procdefinition^.proctypeoption<>potype_constructor)) then
  1612. Message(parser_e_expr_have_to_be_constructor_call);
  1613. end;
  1614. p1:=gensinglenode(newn,p1);
  1615. { set the resulttype }
  1616. p1^.resulttype:=pd2;
  1617. consume(_RKLAMMER);
  1618. end;
  1619. postfixoperators;
  1620. end;
  1621. _SELF : begin
  1622. again:=true;
  1623. consume(_SELF);
  1624. if not assigned(procinfo^._class) then
  1625. begin
  1626. p1:=genzeronode(errorn);
  1627. pd:=generrordef;
  1628. again:=false;
  1629. Message(parser_e_self_not_in_method);
  1630. end
  1631. else
  1632. begin
  1633. if (po_classmethod in aktprocsym^.definition^.procoptions) then
  1634. begin
  1635. { self in class methods is a class reference type }
  1636. pd:=new(pclassrefdef,init(procinfo^._class));
  1637. p1:=genselfnode(pd);
  1638. p1^.resulttype:=pd;
  1639. end
  1640. else
  1641. begin
  1642. p1:=genselfnode(procinfo^._class);
  1643. p1^.resulttype:=procinfo^._class;
  1644. end;
  1645. pd:=p1^.resulttype;
  1646. postfixoperators;
  1647. end;
  1648. end;
  1649. _INHERITED : begin
  1650. again:=true;
  1651. consume(_INHERITED);
  1652. if assigned(procinfo^._class) then
  1653. begin
  1654. { if inherited; only then we need the method with
  1655. the same name }
  1656. if token=_SEMICOLON then
  1657. begin
  1658. hs:=aktprocsym^.name;
  1659. auto_inherited:=true
  1660. end
  1661. else
  1662. begin
  1663. hs:=pattern;
  1664. consume(_ID);
  1665. auto_inherited:=false;
  1666. end;
  1667. classh:=procinfo^._class^.childof;
  1668. while assigned(classh) do
  1669. begin
  1670. srsymtable:=pobjectdef(classh)^.symtable;
  1671. sym:=srsymtable^.search(hs);
  1672. if assigned(sym) then
  1673. begin
  1674. { only for procsyms we need to set the type (PFV) }
  1675. case sym^.typ of
  1676. procsym :
  1677. begin
  1678. p1:=genzeronode(typen);
  1679. p1^.resulttype:=classh;
  1680. pd:=p1^.resulttype;
  1681. end;
  1682. varsym :
  1683. begin
  1684. p1:=nil;
  1685. pd:=pvarsym(sym)^.vartype.def;
  1686. end;
  1687. propertysym :
  1688. begin
  1689. p1:=nil;
  1690. pd:=ppropertysym(sym)^.proptype.def;
  1691. end;
  1692. else
  1693. internalerror(83251763);
  1694. end;
  1695. do_member_read(false,sym,p1,pd,again);
  1696. break;
  1697. end;
  1698. classh:=classh^.childof;
  1699. end;
  1700. if classh=nil then
  1701. begin
  1702. Message1(sym_e_id_no_member,hs);
  1703. again:=false;
  1704. pd:=generrordef;
  1705. p1:=genzeronode(errorn);
  1706. end;
  1707. { turn auto inheriting off }
  1708. auto_inherited:=false;
  1709. end
  1710. else
  1711. begin
  1712. Message(parser_e_generic_methods_only_in_methods);
  1713. again:=false;
  1714. pd:=generrordef;
  1715. p1:=genzeronode(errorn);
  1716. end;
  1717. postfixoperators;
  1718. end;
  1719. _INTCONST : begin
  1720. valint(pattern,l,code);
  1721. if code<>0 then
  1722. begin
  1723. val(pattern,d,code);
  1724. if code<>0 then
  1725. begin
  1726. Message(cg_e_invalid_integer);
  1727. consume(_INTCONST);
  1728. l:=1;
  1729. p1:=genordinalconstnode(l,s32bitdef);
  1730. end
  1731. else
  1732. begin
  1733. consume(_INTCONST);
  1734. p1:=genrealconstnode(d,bestrealdef^);
  1735. end;
  1736. end
  1737. else
  1738. begin
  1739. consume(_INTCONST);
  1740. p1:=genordinalconstnode(l,s32bitdef);
  1741. end;
  1742. end;
  1743. _REALNUMBER : begin
  1744. val(pattern,d,code);
  1745. if code<>0 then
  1746. begin
  1747. Message(parser_e_error_in_real);
  1748. d:=1.0;
  1749. end;
  1750. consume(_REALNUMBER);
  1751. p1:=genrealconstnode(d,bestrealdef^);
  1752. end;
  1753. _STRING : begin
  1754. pd:=string_dec;
  1755. { STRING can be also a type cast }
  1756. if token=_LKLAMMER then
  1757. begin
  1758. consume(_LKLAMMER);
  1759. p1:=comp_expr(true);
  1760. consume(_RKLAMMER);
  1761. p1:=gentypeconvnode(p1,pd);
  1762. p1^.explizit:=true;
  1763. { handle postfix operators here e.g. string(a)[10] }
  1764. again:=true;
  1765. postfixoperators;
  1766. end
  1767. else
  1768. p1:=gentypenode(pd,nil);
  1769. end;
  1770. _FILE : begin
  1771. pd:=cfiledef;
  1772. consume(_FILE);
  1773. { FILE can be also a type cast }
  1774. if token=_LKLAMMER then
  1775. begin
  1776. consume(_LKLAMMER);
  1777. p1:=comp_expr(true);
  1778. consume(_RKLAMMER);
  1779. p1:=gentypeconvnode(p1,pd);
  1780. p1^.explizit:=true;
  1781. { handle postfix operators here e.g. string(a)[10] }
  1782. again:=true;
  1783. postfixoperators;
  1784. end
  1785. else
  1786. p1:=gentypenode(pd,nil);
  1787. end;
  1788. _CSTRING : begin
  1789. p1:=genstringconstnode(pattern,st_default);
  1790. consume(_CSTRING);
  1791. end;
  1792. _CCHAR : begin
  1793. p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1794. consume(_CCHAR);
  1795. end;
  1796. _KLAMMERAFFE : begin
  1797. consume(_KLAMMERAFFE);
  1798. got_addrn:=true;
  1799. { support both @<x> and @(<x>) }
  1800. if token=_LKLAMMER then
  1801. begin
  1802. consume(_LKLAMMER);
  1803. p1:=factor(true);
  1804. consume(_RKLAMMER);
  1805. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1806. begin
  1807. { we need the resulttype }
  1808. { of the expression in pd }
  1809. do_firstpass(p1);
  1810. pd:=p1^.resulttype;
  1811. again:=true;
  1812. postfixoperators;
  1813. end;
  1814. end
  1815. else
  1816. p1:=factor(true);
  1817. got_addrn:=false;
  1818. p1:=gensinglenode(addrn,p1);
  1819. end;
  1820. _LKLAMMER : begin
  1821. consume(_LKLAMMER);
  1822. p1:=comp_expr(true);
  1823. consume(_RKLAMMER);
  1824. { it's not a good solution }
  1825. { but (a+b)^ makes some problems }
  1826. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1827. begin
  1828. { we need the resulttype }
  1829. { of the expression in pd }
  1830. do_firstpass(p1);
  1831. pd:=p1^.resulttype;
  1832. again:=true;
  1833. postfixoperators;
  1834. end;
  1835. end;
  1836. _LECKKLAMMER : begin
  1837. consume(_LECKKLAMMER);
  1838. p1:=factor_read_set;
  1839. consume(_RECKKLAMMER);
  1840. end;
  1841. _PLUS : begin
  1842. consume(_PLUS);
  1843. p1:=factor(false);
  1844. end;
  1845. _MINUS : begin
  1846. consume(_MINUS);
  1847. p1:=sub_expr(oppower,false);
  1848. p1:=gensinglenode(unaryminusn,p1);
  1849. end;
  1850. _OP_NOT : begin
  1851. consume(_OP_NOT);
  1852. p1:=factor(false);
  1853. p1:=gensinglenode(notn,p1);
  1854. end;
  1855. _TRUE : begin
  1856. consume(_TRUE);
  1857. p1:=genordinalconstnode(1,booldef);
  1858. end;
  1859. _FALSE : begin
  1860. consume(_FALSE);
  1861. p1:=genordinalconstnode(0,booldef);
  1862. end;
  1863. _NIL : begin
  1864. consume(_NIL);
  1865. p1:=genzeronode(niln);
  1866. end;
  1867. else
  1868. begin
  1869. p1:=genzeronode(errorn);
  1870. consume(token);
  1871. Message(cg_e_illegal_expression);
  1872. end;
  1873. end;
  1874. { generate error node if no node is created }
  1875. if not assigned(p1) then
  1876. p1:=genzeronode(errorn);
  1877. { tp7 procvar handling, but not if the next token
  1878. will be a := }
  1879. if (m_tp_procvar in aktmodeswitches) and
  1880. (token<>_ASSIGNMENT) then
  1881. check_tp_procvar(p1);
  1882. factor:=p1;
  1883. check_tokenpos;
  1884. end;
  1885. {$ifdef fpc}
  1886. {$maxfpuregisters default}
  1887. {$endif fpc}
  1888. {****************************************************************************
  1889. Sub_Expr
  1890. ****************************************************************************}
  1891. const
  1892. { Warning these stay be ordered !! }
  1893. operator_levels:array[Toperator_precedence] of set of Ttoken=
  1894. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN,_OP_IS],
  1895. [_PLUS,_MINUS,_OP_OR,_OP_XOR],
  1896. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
  1897. _OP_AS,_OP_AND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
  1898. [_STARSTAR] );
  1899. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;
  1900. {Reads a subexpression while the operators are of the current precedence
  1901. level, or any higher level. Replaces the old term, simpl_expr and
  1902. simpl2_expr.}
  1903. var
  1904. low,high,mid : longint;
  1905. p1,p2 : Ptree;
  1906. oldt : Ttoken;
  1907. filepos : tfileposinfo;
  1908. begin
  1909. if pred_level=highest_precedence then
  1910. p1:=factor(false)
  1911. else
  1912. p1:=sub_expr(succ(pred_level),true);
  1913. repeat
  1914. if (token in operator_levels[pred_level]) and
  1915. ((token<>_EQUAL) or accept_equal) then
  1916. begin
  1917. oldt:=token;
  1918. filepos:=tokenpos;
  1919. consume(token);
  1920. if pred_level=highest_precedence then
  1921. p2:=factor(false)
  1922. else
  1923. p2:=sub_expr(succ(pred_level),true);
  1924. low:=1;
  1925. high:=tok2nodes;
  1926. while (low<high) do
  1927. begin
  1928. mid:=(low+high+1) shr 1;
  1929. if oldt<tok2node[mid].tok then
  1930. high:=mid-1
  1931. else
  1932. low:=mid;
  1933. end;
  1934. if tok2node[high].tok=oldt then
  1935. p1:=gennode(tok2node[high].nod,p1,p2)
  1936. else
  1937. p1:=gennode(nothingn,p1,p2);
  1938. set_tree_filepos(p1,filepos);
  1939. end
  1940. else
  1941. break;
  1942. until false;
  1943. sub_expr:=p1;
  1944. end;
  1945. function comp_expr(accept_equal : boolean):Ptree;
  1946. var
  1947. oldafterassignment : boolean;
  1948. p1 : ptree;
  1949. begin
  1950. oldafterassignment:=afterassignment;
  1951. afterassignment:=true;
  1952. p1:=sub_expr(opcompare,accept_equal);
  1953. afterassignment:=oldafterassignment;
  1954. comp_expr:=p1;
  1955. end;
  1956. function expr : ptree;
  1957. var
  1958. p1,p2 : ptree;
  1959. oldafterassignment : boolean;
  1960. oldp1 : ptree;
  1961. filepos : tfileposinfo;
  1962. begin
  1963. oldafterassignment:=afterassignment;
  1964. p1:=sub_expr(opcompare,true);
  1965. filepos:=tokenpos;
  1966. if (m_tp_procvar in aktmodeswitches) and
  1967. (token<>_ASSIGNMENT) then
  1968. check_tp_procvar(p1);
  1969. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1970. afterassignment:=true;
  1971. oldp1:=p1;
  1972. case token of
  1973. _POINTPOINT : begin
  1974. consume(_POINTPOINT);
  1975. p2:=sub_expr(opcompare,true);
  1976. p1:=gennode(rangen,p1,p2);
  1977. end;
  1978. _ASSIGNMENT : begin
  1979. consume(_ASSIGNMENT);
  1980. { avoid a firstpass of a procedure if
  1981. it must be assigned to a procvar }
  1982. { should be recursive for a:=b:=c !!! }
  1983. if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1984. begin
  1985. getprocvar:=true;
  1986. getprocvardef:=pprocvardef(p1^.resulttype);
  1987. end;
  1988. p2:=sub_expr(opcompare,true);
  1989. if getprocvar then
  1990. handle_procvar(getprocvardef,p2);
  1991. getprocvar:=false;
  1992. p1:=gennode(assignn,p1,p2);
  1993. end;
  1994. { this is the code for C like assignements }
  1995. { from an improvement of Peter Schaefer }
  1996. _PLUSASN : begin
  1997. consume(_PLUSASN );
  1998. p2:=sub_expr(opcompare,true);
  1999. p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  2000. { was first
  2001. p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  2002. but disposetree assumes that we have a real
  2003. *** tree *** }
  2004. end;
  2005. _MINUSASN : begin
  2006. consume(_MINUSASN );
  2007. p2:=sub_expr(opcompare,true);
  2008. p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  2009. end;
  2010. _STARASN : begin
  2011. consume(_STARASN );
  2012. p2:=sub_expr(opcompare,true);
  2013. p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  2014. end;
  2015. _SLASHASN : begin
  2016. consume(_SLASHASN );
  2017. p2:=sub_expr(opcompare,true);
  2018. p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  2019. end;
  2020. end;
  2021. afterassignment:=oldafterassignment;
  2022. if p1<>oldp1 then
  2023. set_tree_filepos(p1,filepos);
  2024. expr:=p1;
  2025. end;
  2026. function get_intconst:longint;
  2027. {Reads an expression, tries to evalute it and check if it is an integer
  2028. constant. Then the constant is returned.}
  2029. var
  2030. p:Ptree;
  2031. begin
  2032. p:=comp_expr(true);
  2033. do_firstpass(p);
  2034. if not codegenerror then
  2035. begin
  2036. if (p^.treetype<>ordconstn) and
  2037. (p^.resulttype^.deftype=orddef) and
  2038. not(Porddef(p^.resulttype)^.typ in [uvoid,uchar,bool8bit,bool16bit,bool32bit]) then
  2039. Message(cg_e_illegal_expression)
  2040. else
  2041. get_intconst:=p^.value;
  2042. end;
  2043. disposetree(p);
  2044. end;
  2045. function get_stringconst:string;
  2046. {Reads an expression, tries to evaluate it and checks if it is a string
  2047. constant. Then the constant is returned.}
  2048. var
  2049. p:Ptree;
  2050. begin
  2051. get_stringconst:='';
  2052. p:=comp_expr(true);
  2053. do_firstpass(p);
  2054. if p^.treetype<>stringconstn then
  2055. begin
  2056. if (p^.treetype=ordconstn) and is_char(p^.resulttype) then
  2057. get_stringconst:=char(p^.value)
  2058. else
  2059. Message(cg_e_illegal_expression);
  2060. end
  2061. else
  2062. get_stringconst:=strpas(p^.value_str);
  2063. disposetree(p);
  2064. end;
  2065. end.
  2066. {
  2067. $Log$
  2068. Revision 1.3 2000-08-04 22:00:52 peter
  2069. * merges from fixes
  2070. Revision 1.2 2000/07/13 11:32:44 michael
  2071. + removed logs
  2072. }