pexpr.pas 84 KB

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