PARS.ob07 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2022, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE PARS;
  7. IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS,
  8. C := COLLECTIONS, TARGETS, THUMB, MSP430;
  9. CONST
  10. eCONST* = 1; eTYPE* = 2; eVAR* = 3; eEXPR* = 4;
  11. eVREC* = 5; ePROC* = 6; eVPAR* = 7; ePARAM* = 8;
  12. eSTPROC* = 9; eSTFUNC* = 10; eSYSFUNC* = 11; eSYSPROC* = 12;
  13. eIMP* = 13;
  14. TYPE
  15. PATH* = PATHS.PATH;
  16. PARSER* = POINTER TO rPARSER;
  17. POSITION* = RECORD (SCAN.POSITION)
  18. parser*: PARSER
  19. END;
  20. EXPR* = RECORD
  21. obj*: INTEGER;
  22. _type*: PROG._TYPE;
  23. value*: ARITH.VALUE;
  24. stproc*: INTEGER;
  25. readOnly*: BOOLEAN;
  26. ident*: PROG.IDENT
  27. END;
  28. STATPROC = PROCEDURE (parser: PARSER);
  29. EXPRPROC = PROCEDURE (parser: PARSER; VAR e: EXPR);
  30. RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG._TYPE; pos: POSITION): BOOLEAN;
  31. rPARSER = RECORD (C.ITEM)
  32. fname*: PATH;
  33. path: PATH;
  34. lib_path: PATH;
  35. ext: PATH;
  36. modname: PATH;
  37. scanner: SCAN.SCANNER;
  38. lex*: SCAN.LEX;
  39. sym*: INTEGER;
  40. unit*: PROG.UNIT;
  41. constexp*: BOOLEAN;
  42. main*: BOOLEAN;
  43. open*: PROCEDURE (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN;
  44. parse*: PROCEDURE (parser: PARSER);
  45. StatSeq*: STATPROC;
  46. expression*: EXPRPROC;
  47. designator*: EXPRPROC;
  48. chkreturn: RETPROC;
  49. create*: PROCEDURE (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER
  50. END;
  51. VAR
  52. parsers: C.COLLECTION;
  53. lines*, modules: INTEGER;
  54. PROCEDURE destroy* (VAR parser: PARSER);
  55. BEGIN
  56. IF parser.scanner # NIL THEN
  57. SCAN.close(parser.scanner)
  58. END;
  59. C.push(parsers, parser);
  60. parser := NIL
  61. END destroy;
  62. PROCEDURE getpos (parser: PARSER; VAR pos: POSITION);
  63. BEGIN
  64. pos.line := parser.lex.pos.line;
  65. pos.col := parser.lex.pos.col;
  66. pos.parser := parser
  67. END getpos;
  68. PROCEDURE error* (pos: POSITION; errno: INTEGER);
  69. BEGIN
  70. ERRORS.ErrorMsg(pos.parser.fname, pos.line, pos.col, errno)
  71. END error;
  72. PROCEDURE check* (condition: BOOLEAN; pos: POSITION; errno: INTEGER);
  73. BEGIN
  74. IF ~condition THEN
  75. error(pos, errno)
  76. END
  77. END check;
  78. PROCEDURE check1* (condition: BOOLEAN; parser: PARSER; errno: INTEGER);
  79. VAR
  80. pos: POSITION;
  81. BEGIN
  82. IF ~condition THEN
  83. getpos(parser, pos);
  84. error(pos, errno)
  85. END
  86. END check1;
  87. PROCEDURE Next* (parser: PARSER);
  88. VAR
  89. errno: INTEGER;
  90. BEGIN
  91. SCAN.Next(parser.scanner, parser.lex);
  92. errno := parser.lex.error;
  93. IF errno = 0 THEN
  94. IF (TARGETS.RealSize = 0) & (parser.lex.sym = SCAN.lxFLOAT) THEN
  95. errno := -SCAN.lxERROR13
  96. ELSIF (TARGETS.BitDepth = 16) & (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN
  97. errno := -SCAN.lxERROR10
  98. END
  99. END;
  100. IF errno # 0 THEN
  101. check1(FALSE, parser, errno)
  102. END;
  103. parser.sym := parser.lex.sym
  104. END Next;
  105. PROCEDURE NextPos (parser: PARSER; VAR pos: POSITION);
  106. BEGIN
  107. Next(parser);
  108. getpos(parser, pos)
  109. END NextPos;
  110. PROCEDURE checklex* (parser: PARSER; sym: INTEGER);
  111. VAR
  112. err: INTEGER;
  113. BEGIN
  114. IF parser.sym # sym THEN
  115. CASE sym OF
  116. |SCAN.lxCOMMA: err := 65
  117. |SCAN.lxRROUND: err := 33
  118. |SCAN.lxPOINT: err := 26
  119. |SCAN.lxIDENT: err := 22
  120. |SCAN.lxRSQUARE: err := 71
  121. |SCAN.lxRCURLY: err := 35
  122. |SCAN.lxUNDEF: err := 34
  123. |SCAN.lxTHEN: err := 88
  124. |SCAN.lxEND: err := 27
  125. |SCAN.lxDO: err := 89
  126. |SCAN.lxUNTIL: err := 90
  127. |SCAN.lxCOLON: err := 53
  128. |SCAN.lxOF: err := 67
  129. |SCAN.lxASSIGN: err := 96
  130. |SCAN.lxTO: err := 57
  131. |SCAN.lxLROUND: err := 64
  132. |SCAN.lxEQ: err := 32
  133. |SCAN.lxSEMI: err := 24
  134. |SCAN.lxRETURN: err := 38
  135. |SCAN.lxMODULE: err := 21
  136. END;
  137. check1(FALSE, parser, err)
  138. END
  139. END checklex;
  140. PROCEDURE ExpectSym* (parser: PARSER; sym: INTEGER);
  141. BEGIN
  142. Next(parser);
  143. checklex(parser, sym)
  144. END ExpectSym;
  145. PROCEDURE ImportList (parser: PARSER);
  146. VAR
  147. fname, path, ext, _name: PATH;
  148. name: SCAN.IDENT;
  149. parser2: PARSER;
  150. pos: POSITION;
  151. alias, _in: BOOLEAN;
  152. unit: PROG.UNIT;
  153. ident: PROG.IDENT;
  154. BEGIN
  155. alias := FALSE;
  156. REPEAT
  157. ExpectSym(parser, SCAN.lxIDENT);
  158. name := parser.lex.ident;
  159. getpos(parser, pos);
  160. IF ~alias THEN
  161. ident := PROG.addIdent(parser.unit, name, PROG.idMODULE);
  162. check(ident # NIL, pos, 30)
  163. END;
  164. Next(parser);
  165. path := parser.path;
  166. fname := "";
  167. ext := UTILS.FILE_EXT;
  168. COPY(name.s, _name);
  169. _in := FALSE;
  170. IF parser.sym = SCAN.lxIN THEN
  171. _in := TRUE;
  172. Next(parser);
  173. IF parser.sym = SCAN.lxSTRING THEN
  174. STRINGS.trim(parser.lex.string.s, fname)
  175. ELSIF parser.sym = SCAN.lxCHAR THEN
  176. fname[0] := CHR(ARITH.Int(parser.lex.value));
  177. fname[1] := 0X
  178. ELSE
  179. check1(FALSE, parser, 117)
  180. END;
  181. STRINGS.replace(fname, "/", UTILS.slash);
  182. STRINGS.replace(fname, "\", UTILS.slash);
  183. PATHS.DelSlashes(fname);
  184. PATHS.split(fname, path, _name, ext);
  185. IF PATHS.isRelative(path) THEN
  186. PATHS.RelPath(parser.path, path, fname);
  187. STRINGS.append(fname, _name);
  188. STRINGS.append(fname, ext);
  189. PATHS.split(fname, path, _name, ext)
  190. END;
  191. Next(parser)
  192. END;
  193. IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN
  194. alias := FALSE;
  195. IF (fname = "") & ((_name = "SYSTEM") OR PROG.LowerCase & (_name = "system")) THEN
  196. unit := PROG.program.sysunit
  197. ELSE
  198. IF fname # "" THEN
  199. unit := PROG.getUnit(fname)
  200. ELSE
  201. fname := path;
  202. STRINGS.append(fname, _name);
  203. STRINGS.append(fname, UTILS.FILE_EXT);
  204. unit := PROG.getUnit(fname);
  205. IF unit = NIL THEN
  206. fname := parser.lib_path;
  207. STRINGS.append(fname, _name);
  208. STRINGS.append(fname, UTILS.FILE_EXT);
  209. unit := PROG.getUnit(fname)
  210. END
  211. END
  212. END;
  213. IF unit # NIL THEN
  214. check(unit.closed, pos, 31)
  215. ELSE
  216. parser2 := parser.create(path, parser.lib_path,
  217. parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
  218. IF ~parser2.open(parser2, _name, ext) THEN
  219. IF (path # parser.lib_path) & ~_in THEN
  220. destroy(parser2);
  221. parser2 := parser.create(parser.lib_path, parser.lib_path,
  222. parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
  223. check(parser2.open(parser2, _name, ext), pos, 29)
  224. ELSE
  225. error(pos, 29)
  226. END
  227. END;
  228. parser2.parse(parser2);
  229. unit := parser2.unit;
  230. unit.fname := parser2.fname;
  231. destroy(parser2)
  232. END;
  233. IF unit = PROG.program.sysunit THEN
  234. parser.unit.sysimport := TRUE
  235. END;
  236. ident.unit := unit
  237. ELSIF parser.sym = SCAN.lxASSIGN THEN
  238. alias := TRUE
  239. ELSE
  240. check1(FALSE, parser, 28)
  241. END
  242. UNTIL parser.sym = SCAN.lxSEMI;
  243. Next(parser)
  244. END ImportList;
  245. PROCEDURE QIdent (parser: PARSER; forward: BOOLEAN): PROG.IDENT;
  246. VAR
  247. ident: PROG.IDENT;
  248. unit: PROG.UNIT;
  249. BEGIN
  250. ASSERT(parser.sym = SCAN.lxIDENT);
  251. ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE);
  252. IF ~forward THEN
  253. check1(ident # NIL, parser, 48)
  254. END;
  255. IF (ident # NIL) & (ident.typ = PROG.idMODULE) THEN
  256. unit := ident.unit;
  257. ExpectSym(parser, SCAN.lxPOINT);
  258. ExpectSym(parser, SCAN.lxIDENT);
  259. ident := PROG.getIdent(unit, parser.lex.ident, FALSE);
  260. check1((ident # NIL) & ident.export, parser, 48)
  261. END
  262. RETURN ident
  263. END QIdent;
  264. PROCEDURE strcmp* (VAR v: ARITH.VALUE; v2: ARITH.VALUE; operator: INTEGER);
  265. VAR
  266. str: SCAN.TEXTSTR;
  267. string1, string2: SCAN.STRING;
  268. bool: BOOLEAN;
  269. BEGIN
  270. IF v.typ = ARITH.tCHAR THEN
  271. ASSERT(v2.typ = ARITH.tSTRING);
  272. ARITH.charToStr(v, str);
  273. string1 := SCAN.enterStr(str);
  274. string2 := v2.string(SCAN.STRING)
  275. END;
  276. IF v2.typ = ARITH.tCHAR THEN
  277. ASSERT(v.typ = ARITH.tSTRING);
  278. ARITH.charToStr(v2, str);
  279. string2 := SCAN.enterStr(str);
  280. string1 := v.string(SCAN.STRING)
  281. END;
  282. IF v.typ = v2.typ THEN
  283. string1 := v.string(SCAN.STRING);
  284. string2 := v2.string(SCAN.STRING)
  285. END;
  286. CASE operator OF
  287. |SCAN.lxEQ: bool := string1.s = string2.s
  288. |SCAN.lxNE: bool := string1.s # string2.s
  289. |SCAN.lxLT: bool := string1.s < string2.s
  290. |SCAN.lxGT: bool := string1.s > string2.s
  291. |SCAN.lxLE: bool := string1.s <= string2.s
  292. |SCAN.lxGE: bool := string1.s >= string2.s
  293. END;
  294. ARITH.setbool(v, bool)
  295. END strcmp;
  296. PROCEDURE ConstExpression* (parser: PARSER; VAR v: ARITH.VALUE);
  297. VAR
  298. e: EXPR;
  299. pos: POSITION;
  300. BEGIN
  301. getpos(parser, pos);
  302. parser.constexp := TRUE;
  303. parser.expression(parser, e);
  304. parser.constexp := FALSE;
  305. check(e.obj = eCONST, pos, 62);
  306. v := e.value
  307. END ConstExpression;
  308. PROCEDURE FieldList (parser: PARSER; rec: PROG._TYPE);
  309. VAR
  310. name: SCAN.IDENT;
  311. export: BOOLEAN;
  312. pos: POSITION;
  313. BEGIN
  314. ASSERT(parser.sym = SCAN.lxIDENT);
  315. WHILE parser.sym = SCAN.lxIDENT DO
  316. getpos(parser, pos);
  317. name := parser.lex.ident;
  318. Next(parser);
  319. export := parser.sym = SCAN.lxMUL;
  320. IF export THEN
  321. check1(parser.unit.scopeLvl = 0, parser, 61);
  322. Next(parser)
  323. END;
  324. check(PROG.addField(rec, name, export), pos, 30);
  325. IF parser.sym = SCAN.lxCOMMA THEN
  326. ExpectSym(parser, SCAN.lxIDENT)
  327. ELSE
  328. checklex(parser, SCAN.lxCOLON)
  329. END
  330. END
  331. END FieldList;
  332. PROCEDURE FormalParameters (parser: PARSER; _type: PROG._TYPE);
  333. VAR
  334. ident: PROG.IDENT;
  335. PROCEDURE FPSection (parser: PARSER; _type: PROG._TYPE);
  336. VAR
  337. ident: PROG.IDENT;
  338. exit: BOOLEAN;
  339. vPar: BOOLEAN;
  340. dim: INTEGER;
  341. t0, t1: PROG._TYPE;
  342. pos: POSITION;
  343. BEGIN
  344. vPar := parser.sym = SCAN.lxVAR;
  345. IF vPar THEN
  346. Next(parser)
  347. END;
  348. checklex(parser, SCAN.lxIDENT);
  349. exit := FALSE;
  350. WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO
  351. check1(PROG.addParam(_type, parser.lex.ident, vPar), parser, 30);
  352. Next(parser);
  353. IF parser.sym = SCAN.lxCOMMA THEN
  354. ExpectSym(parser, SCAN.lxIDENT)
  355. ELSIF parser.sym = SCAN.lxCOLON THEN
  356. Next(parser);
  357. getpos(parser, pos);
  358. dim := 0;
  359. WHILE parser.sym = SCAN.lxARRAY DO
  360. INC(dim);
  361. check1(dim <= PROG.MAXARRDIM, parser, 84);
  362. ExpectSym(parser, SCAN.lxOF);
  363. Next(parser)
  364. END;
  365. checklex(parser, SCAN.lxIDENT);
  366. ident := QIdent(parser, FALSE);
  367. check1(ident.typ = PROG.idTYPE, parser, 68);
  368. t0 := ident._type;
  369. t1 := t0;
  370. WHILE dim > 0 DO
  371. t1 := PROG.enterType(PROG.tARRAY, -1, 0, parser.unit);
  372. t1.base := t0;
  373. t0 := t1;
  374. DEC(dim)
  375. END;
  376. IF _type.call IN {PROG.fastcall, PROG._fastcall} THEN
  377. check(t1.typ # PROG.tREAL, pos, 126)
  378. END;
  379. PROG.setParams(_type, t1);
  380. Next(parser);
  381. exit := TRUE
  382. ELSE
  383. checklex(parser, SCAN.lxCOLON)
  384. END
  385. END
  386. END FPSection;
  387. BEGIN
  388. IF parser.sym = SCAN.lxLROUND THEN
  389. Next(parser);
  390. IF (parser.sym = SCAN.lxVAR) OR (parser.sym = SCAN.lxIDENT) THEN
  391. FPSection(parser, _type);
  392. WHILE parser.sym = SCAN.lxSEMI DO
  393. Next(parser);
  394. FPSection(parser, _type)
  395. END
  396. END;
  397. checklex(parser, SCAN.lxRROUND);
  398. Next(parser);
  399. IF parser.sym = SCAN.lxCOLON THEN
  400. ExpectSym(parser, SCAN.lxIDENT);
  401. ident := QIdent(parser, FALSE);
  402. check1(ident.typ = PROG.idTYPE, parser, 68);
  403. check1(~(ident._type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69);
  404. check1( ~(ODD(_type.call) & (ident._type.typ = PROG.tREAL)), parser, 113);
  405. _type.base := ident._type;
  406. Next(parser)
  407. ELSE
  408. _type.base := NIL
  409. END
  410. END
  411. END FormalParameters;
  412. PROCEDURE sysflag (parser: PARSER; proc: BOOLEAN): INTEGER;
  413. VAR
  414. res, sf: INTEGER;
  415. BEGIN
  416. checklex(parser, SCAN.lxIDENT);
  417. IF parser.lex.ident.s = "stdcall" THEN
  418. sf := PROG.sf_stdcall
  419. ELSIF parser.lex.ident.s = "cdecl" THEN
  420. sf := PROG.sf_cdecl
  421. ELSIF parser.lex.ident.s = "ccall" THEN
  422. sf := PROG.sf_ccall
  423. ELSIF parser.lex.ident.s = "win64" THEN
  424. sf := PROG.sf_win64
  425. ELSIF parser.lex.ident.s = "systemv" THEN
  426. sf := PROG.sf_systemv
  427. ELSIF parser.lex.ident.s = "windows" THEN
  428. sf := PROG.sf_windows
  429. ELSIF parser.lex.ident.s = "linux" THEN
  430. sf := PROG.sf_linux
  431. ELSIF parser.lex.ident.s = "code" THEN
  432. sf := PROG.sf_code
  433. ELSIF parser.lex.ident.s = "oberon" THEN
  434. sf := PROG.sf_oberon
  435. ELSIF parser.lex.ident.s = "fastcall" THEN
  436. sf := PROG.sf_fastcall
  437. ELSIF parser.lex.ident.s = "noalign" THEN
  438. sf := PROG.sf_noalign
  439. ELSE
  440. check1(FALSE, parser, 124)
  441. END;
  442. check1(sf IN PROG.program.sysflags, parser, 125);
  443. IF proc THEN
  444. check1(sf IN PROG.proc_flags, parser, 123)
  445. ELSE
  446. check1(sf IN PROG.rec_flags, parser, 123)
  447. END;
  448. CASE sf OF
  449. |PROG.sf_stdcall:
  450. res := PROG.stdcall
  451. |PROG.sf_cdecl:
  452. res := PROG.cdecl
  453. |PROG.sf_ccall:
  454. IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN
  455. res := PROG.ccall
  456. ELSIF TARGETS.OS = TARGETS.osWIN64 THEN
  457. res := PROG.win64
  458. ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
  459. res := PROG.systemv
  460. END
  461. |PROG.sf_win64:
  462. res := PROG.win64
  463. |PROG.sf_systemv:
  464. res := PROG.systemv
  465. |PROG.sf_code:
  466. res := PROG.code
  467. |PROG.sf_fastcall:
  468. res := PROG.fastcall
  469. |PROG.sf_oberon:
  470. IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN
  471. res := PROG.default32
  472. ELSIF TARGETS.OS IN {TARGETS.osWIN64, TARGETS.osLINUX64} THEN
  473. res := PROG.default64
  474. END
  475. |PROG.sf_windows:
  476. IF TARGETS.OS = TARGETS.osWIN32 THEN
  477. res := PROG.stdcall
  478. ELSIF TARGETS.OS = TARGETS.osWIN64 THEN
  479. res := PROG.win64
  480. END
  481. |PROG.sf_linux:
  482. IF TARGETS.OS = TARGETS.osLINUX32 THEN
  483. res := PROG.ccall
  484. ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
  485. res := PROG.systemv
  486. END
  487. |PROG.sf_noalign:
  488. res := PROG.noalign
  489. END
  490. RETURN res
  491. END sysflag;
  492. PROCEDURE procflag (parser: PARSER; VAR _import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER;
  493. VAR
  494. call: INTEGER;
  495. dll, proc: SCAN.TEXTSTR;
  496. pos: POSITION;
  497. PROCEDURE getStr (parser: PARSER; VAR name: SCAN.TEXTSTR);
  498. VAR
  499. pos: POSITION;
  500. str: ARITH.VALUE;
  501. BEGIN
  502. getpos(parser, pos);
  503. ConstExpression(parser, str);
  504. IF str.typ = ARITH.tSTRING THEN
  505. name := str.string(SCAN.STRING).s
  506. ELSIF str.typ = ARITH.tCHAR THEN
  507. ARITH.charToStr(str, name)
  508. ELSE
  509. check(FALSE, pos, 117)
  510. END
  511. END getStr;
  512. BEGIN
  513. _import := NIL;
  514. IF parser.sym = SCAN.lxLSQUARE THEN
  515. getpos(parser, pos);
  516. check1(parser.unit.sysimport, parser, 54);
  517. Next(parser);
  518. call := sysflag(parser, TRUE);
  519. Next(parser);
  520. IF parser.sym = SCAN.lxMINUS THEN
  521. Next(parser);
  522. INC(call)
  523. END;
  524. IF isProc & (parser.sym = SCAN.lxCOMMA) THEN
  525. Next(parser);
  526. getStr(parser, dll);
  527. STRINGS.UpCase(dll);
  528. checklex(parser, SCAN.lxCOMMA);
  529. Next(parser);
  530. getStr(parser, proc);
  531. _import := IL.AddImp(dll, proc)
  532. END;
  533. checklex(parser, SCAN.lxRSQUARE);
  534. Next(parser)
  535. ELSE
  536. CASE TARGETS.BitDepth OF
  537. |16: call := PROG.default16
  538. |32: IF TARGETS.CPU = TARGETS.cpuX86 THEN
  539. call := PROG.default32
  540. ELSE
  541. call := PROG.cdecl
  542. END
  543. |64: IF TARGETS.CPU = TARGETS.cpuAMD64 THEN
  544. call := PROG.default64
  545. ELSE
  546. call := PROG.cdecl
  547. END
  548. END
  549. END;
  550. IF _import # NIL THEN
  551. check(TARGETS.Import, pos, 70)
  552. END
  553. RETURN call
  554. END procflag;
  555. PROCEDURE _type (parser: PARSER; VAR t: PROG._TYPE; flags: SET);
  556. CONST
  557. comma = 0;
  558. closed = 1;
  559. forward = 2;
  560. VAR
  561. arrLen: ARITH.VALUE;
  562. typeSize: ARITH.VALUE;
  563. ident: PROG.IDENT;
  564. unit: PROG.UNIT;
  565. pos, pos2: POSITION;
  566. fieldType: PROG._TYPE;
  567. baseIdent: SCAN.IDENT;
  568. a, b: INTEGER;
  569. RecFlag: INTEGER;
  570. _import: IL.IMPORT_PROC;
  571. BEGIN
  572. unit := parser.unit;
  573. t := NIL;
  574. IF parser.sym = SCAN.lxIDENT THEN
  575. ident := QIdent(parser, forward IN flags);
  576. IF ident # NIL THEN
  577. check1(ident.typ = PROG.idTYPE, parser, 49);
  578. t := ident._type;
  579. check1(t # NIL, parser, 50);
  580. IF closed IN flags THEN
  581. check1(t.closed, parser, 50)
  582. END
  583. END;
  584. Next(parser)
  585. ELSIF (parser.sym = SCAN.lxARRAY) OR ((parser.sym = SCAN.lxCOMMA) & (comma IN flags)) THEN
  586. IF parser.sym = SCAN.lxARRAY THEN
  587. getpos(parser, pos2)
  588. END;
  589. NextPos(parser, pos);
  590. ConstExpression(parser, arrLen);
  591. check(arrLen.typ = ARITH.tINTEGER, pos, 43);
  592. check(ARITH.check(arrLen), pos, 39);
  593. check(ARITH.getInt(arrLen) > 0, pos, 51);
  594. t := PROG.enterType(PROG.tARRAY, -1, ARITH.getInt(arrLen), unit);
  595. IF parser.sym = SCAN.lxCOMMA THEN
  596. _type(parser, t.base, {comma, closed})
  597. ELSIF parser.sym = SCAN.lxOF THEN
  598. Next(parser);
  599. _type(parser, t.base, {closed})
  600. ELSE
  601. check1(FALSE, parser, 47)
  602. END;
  603. t.align := t.base.align;
  604. a := t.length;
  605. b := t.base.size;
  606. check(ARITH.mulInt(a, b), pos2, 104);
  607. check(ARITH.setInt(typeSize, a), pos2, 104);
  608. t.size := a;
  609. t.closed := TRUE
  610. ELSIF parser.sym = SCAN.lxRECORD THEN
  611. getpos(parser, pos2);
  612. Next(parser);
  613. t := PROG.enterType(PROG.tRECORD, 0, 0, unit);
  614. t.align := 1;
  615. IF parser.sym = SCAN.lxLSQUARE THEN
  616. check1(parser.unit.sysimport, parser, 54);
  617. Next(parser);
  618. RecFlag := sysflag(parser, FALSE);
  619. t.noalign := RecFlag = PROG.noalign;
  620. ExpectSym(parser, SCAN.lxRSQUARE);
  621. Next(parser)
  622. END;
  623. IF parser.sym = SCAN.lxLROUND THEN
  624. check1(~t.noalign, parser, 111);
  625. ExpectSym(parser, SCAN.lxIDENT);
  626. getpos(parser, pos);
  627. _type(parser, t.base, {closed});
  628. check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, pos, 52);
  629. IF t.base.typ = PROG.tPOINTER THEN
  630. t.base := t.base.base;
  631. check(t.base # NIL, pos, 55)
  632. END;
  633. check(~t.base.noalign, pos, 112);
  634. checklex(parser, SCAN.lxRROUND);
  635. Next(parser);
  636. t.size := t.base.size;
  637. IF t.base.align > t.align THEN
  638. t.align := t.base.align
  639. END
  640. ELSE
  641. t.base := PROG.program.stTypes.tANYREC
  642. END;
  643. WHILE parser.sym = SCAN.lxIDENT DO
  644. FieldList(parser, t);
  645. ASSERT(parser.sym = SCAN.lxCOLON);
  646. Next(parser);
  647. _type(parser, fieldType, {closed});
  648. check(PROG.setFields(t, fieldType), pos2, 104);
  649. IF (fieldType.align > t.align) & ~t.noalign THEN
  650. t.align := fieldType.align
  651. END;
  652. IF parser.sym = SCAN.lxSEMI THEN
  653. ExpectSym(parser, SCAN.lxIDENT)
  654. ELSE
  655. checklex(parser, SCAN.lxEND)
  656. END
  657. END;
  658. t.closed := TRUE;
  659. IL.AddRec(t.base.num);
  660. IF ~t.noalign THEN
  661. check(UTILS.Align(t.size, t.align), pos2, 104);
  662. check(ARITH.setInt(typeSize, t.size), pos2, 104)
  663. END;
  664. checklex(parser, SCAN.lxEND);
  665. Next(parser)
  666. ELSIF parser.sym = SCAN.lxPOINTER THEN
  667. ExpectSym(parser, SCAN.lxTO);
  668. Next(parser);
  669. t := PROG.enterType(PROG.tPOINTER, TARGETS.AdrSize, 0, unit);
  670. t.align := TARGETS.AdrSize;
  671. getpos(parser, pos);
  672. IF parser.sym = SCAN.lxIDENT THEN
  673. baseIdent := parser.lex.ident
  674. END;
  675. _type(parser, t.base, {forward});
  676. IF t.base # NIL THEN
  677. check(t.base.typ = PROG.tRECORD, pos, 58)
  678. ELSE
  679. PROG.frwPtr(unit, t, baseIdent, pos)
  680. END
  681. ELSIF parser.sym = SCAN.lxPROCEDURE THEN
  682. NextPos(parser, pos);
  683. t := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit);
  684. t.align := TARGETS.AdrSize;
  685. t.call := procflag(parser, _import, FALSE);
  686. FormalParameters(parser, t)
  687. ELSE
  688. check1(FALSE, parser, 49)
  689. END
  690. END _type;
  691. PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT;
  692. VAR
  693. ident: PROG.IDENT;
  694. pos: POSITION;
  695. BEGIN
  696. ASSERT(parser.sym = SCAN.lxIDENT);
  697. name := parser.lex.ident;
  698. getpos(parser, pos);
  699. ident := PROG.addIdent(parser.unit, name, typ);
  700. check(ident # NIL, pos, 30);
  701. ident.pos := pos;
  702. Next(parser);
  703. IF parser.sym = SCAN.lxMUL THEN
  704. check1(ident.global, parser, 61);
  705. ident.export := TRUE;
  706. Next(parser)
  707. END
  708. RETURN ident
  709. END IdentDef;
  710. PROCEDURE ConstTypeDeclaration (parser: PARSER; _const: BOOLEAN);
  711. VAR
  712. ident: PROG.IDENT;
  713. name: SCAN.IDENT;
  714. pos: POSITION;
  715. BEGIN
  716. IF _const THEN
  717. ident := IdentDef(parser, PROG.idNONE, name)
  718. ELSE
  719. ident := IdentDef(parser, PROG.idTYPE, name)
  720. END;
  721. checklex(parser, SCAN.lxEQ);
  722. NextPos(parser, pos);
  723. IF _const THEN
  724. ConstExpression(parser, ident.value);
  725. IF ident.value.typ = ARITH.tINTEGER THEN
  726. check(ARITH.check(ident.value), pos, 39)
  727. ELSIF ident.value.typ = ARITH.tREAL THEN
  728. check(ARITH.check(ident.value), pos, 40)
  729. END;
  730. ident.typ := PROG.idCONST;
  731. ident._type := PROG.getType(ident.value.typ)
  732. ELSE
  733. _type(parser, ident._type, {})
  734. END;
  735. checklex(parser, SCAN.lxSEMI);
  736. Next(parser)
  737. END ConstTypeDeclaration;
  738. PROCEDURE VarDeclaration (parser: PARSER);
  739. VAR
  740. ident: PROG.IDENT;
  741. name: SCAN.IDENT;
  742. t: PROG._TYPE;
  743. BEGIN
  744. REPEAT
  745. ident := IdentDef(parser, PROG.idVAR, name);
  746. IF parser.sym = SCAN.lxCOMMA THEN
  747. ExpectSym(parser, SCAN.lxIDENT)
  748. ELSIF parser.sym = SCAN.lxCOLON THEN
  749. Next(parser);
  750. _type(parser, t, {});
  751. PROG.setVarsType(parser.unit, t);
  752. checklex(parser, SCAN.lxSEMI);
  753. Next(parser)
  754. ELSE
  755. checklex(parser, SCAN.lxCOLON)
  756. END
  757. UNTIL parser.sym # SCAN.lxIDENT
  758. END VarDeclaration;
  759. PROCEDURE DeclarationSequence (parser: PARSER): BOOLEAN;
  760. VAR
  761. ptr: PROG.FRWPTR;
  762. endmod: BOOLEAN;
  763. pos: POSITION;
  764. PROCEDURE ProcDeclaration (parser: PARSER): BOOLEAN;
  765. VAR
  766. proc: PROG.IDENT;
  767. endname,
  768. name: SCAN.IDENT;
  769. param: PROG.PARAM;
  770. unit: PROG.UNIT;
  771. ident: PROG.IDENT;
  772. e: EXPR;
  773. pos, pos1,
  774. pos2: POSITION;
  775. label: INTEGER;
  776. enter: IL.COMMAND;
  777. call: INTEGER;
  778. t: PROG._TYPE;
  779. _import: IL.IMPORT_PROC;
  780. endmod, b: BOOLEAN;
  781. fparams: SET;
  782. int, flt: INTEGER;
  783. comma: BOOLEAN;
  784. code, iv: ARITH.VALUE;
  785. codeProc,
  786. handler: BOOLEAN;
  787. line: INTEGER;
  788. BEGIN
  789. endmod := FALSE;
  790. handler := FALSE;
  791. unit := parser.unit;
  792. call := procflag(parser, _import, TRUE);
  793. getpos(parser, pos);
  794. pos1 := pos;
  795. checklex(parser, SCAN.lxIDENT);
  796. line := pos.line;
  797. IF _import # NIL THEN
  798. proc := IdentDef(parser, PROG.idIMP, name);
  799. proc._import := _import;
  800. IF _import.name = "" THEN
  801. COPY(name.s, _import.name)
  802. END;
  803. PROG.program.procs.last(PROG.PROC)._import := _import
  804. ELSE
  805. proc := IdentDef(parser, PROG.idPROC, name)
  806. END;
  807. check(PROG.openScope(unit, proc.proc), pos, 116);
  808. proc._type := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit);
  809. t := proc._type;
  810. t.align := TARGETS.AdrSize;
  811. t.call := call;
  812. FormalParameters(parser, t);
  813. IF parser.sym = SCAN.lxLSQUARE THEN
  814. getpos(parser, pos2);
  815. check((TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE), pos2, 24);
  816. Next(parser);
  817. getpos(parser, pos2);
  818. ConstExpression(parser, iv);
  819. check(iv.typ = ARITH.tINTEGER, pos2, 43);
  820. check((0 <= ARITH.Int(iv)) & (ARITH.Int(iv) <= THUMB.maxIVT), pos2, 46);
  821. check(THUMB.SetIV(ARITH.Int(iv)), pos2, 121);
  822. checklex(parser, SCAN.lxRSQUARE);
  823. Next(parser);
  824. handler := TRUE
  825. END;
  826. codeProc := call IN {PROG.code, PROG._code};
  827. IF call IN {PROG.systemv, PROG._systemv} THEN
  828. check(t.parSize <= PROG.MAXSYSVPARAM, pos, 120)
  829. END;
  830. param := t.params.first(PROG.PARAM);
  831. WHILE param # NIL DO
  832. ident := PROG.addIdent(unit, param.name, PROG.idPARAM);
  833. ASSERT(ident # NIL);
  834. ident._type := param._type;
  835. ident.offset := param.offset;
  836. IF param.vPar THEN
  837. ident.typ := PROG.idVPAR
  838. END;
  839. param := param.next(PROG.PARAM)
  840. END;
  841. IF _import = NIL THEN
  842. label := IL.NewLabel();
  843. proc.proc.label := label;
  844. proc.proc.used := handler;
  845. IF handler THEN
  846. IL.AddCmd2(IL.opHANDLER, label, ARITH.Int(iv))
  847. END
  848. END;
  849. IF codeProc THEN
  850. enter := IL.EnterC(label);
  851. comma := FALSE;
  852. WHILE (parser.sym # SCAN.lxSEMI) OR comma DO
  853. getpos(parser, pos2);
  854. ConstExpression(parser, code);
  855. check(code.typ = ARITH.tINTEGER, pos2, 43);
  856. IF TARGETS.WordSize > TARGETS.InstrSize THEN
  857. CASE TARGETS.InstrSize OF
  858. |1: check(ARITH.range(code, 0, 255), pos, 42)
  859. |2: check(ARITH.range(code, 0, 65535), pos, 110)
  860. END
  861. END;
  862. IL.AddCmd(IL.opCODE, ARITH.getInt(code));
  863. comma := parser.sym = SCAN.lxCOMMA;
  864. IF comma THEN
  865. Next(parser)
  866. ELSE
  867. checklex(parser, SCAN.lxSEMI)
  868. END
  869. END
  870. END;
  871. checklex(parser, SCAN.lxSEMI);
  872. Next(parser);
  873. IF _import = NIL THEN
  874. IF parser.main & proc.export & TARGETS.Dll THEN
  875. IF TARGETS.target = TARGETS.KolibriOSDLL THEN
  876. check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114)
  877. END;
  878. IL.AddExp(label, proc.name.s);
  879. proc.proc.used := TRUE
  880. END;
  881. IF ~codeProc THEN
  882. b := DeclarationSequence(parser)
  883. END;
  884. PROG.ResetLocSize;
  885. IF call IN {PROG._win64, PROG.win64} THEN
  886. fparams := PROG.getFloatParamsPos(proc._type, 3, int, flt);
  887. enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc._type.parSize, 4))
  888. ELSIF call IN {PROG._systemv, PROG.systemv} THEN
  889. fparams := PROG.getFloatParamsPos(proc._type, PROG.MAXSYSVPARAM - 1, int, flt);
  890. enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc._type.parSize))
  891. ELSIF codeProc THEN
  892. ELSIF call IN {PROG.fastcall, PROG._fastcall} THEN
  893. enter := IL.Enter(label, proc._type.parSize)
  894. ELSE
  895. enter := IL.Enter(label, 0)
  896. END;
  897. proc.proc.enter := enter;
  898. IF ~codeProc & (parser.sym = SCAN.lxBEGIN) THEN
  899. Next(parser);
  900. parser.StatSeq(parser)
  901. END;
  902. IF ~codeProc & (t.base # NIL) THEN
  903. checklex(parser, SCAN.lxRETURN);
  904. NextPos(parser, pos);
  905. parser.expression(parser, e);
  906. check(parser.chkreturn(parser, e, t.base, pos), pos, 87)
  907. END;
  908. IF ~codeProc THEN
  909. proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), PROG.program.locsize,
  910. t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv})));
  911. enter.param2 := PROG.program.locsize;
  912. checklex(parser, SCAN.lxEND)
  913. ELSE
  914. proc.proc.leave := IL.LeaveC()
  915. END;
  916. IF (TARGETS.CPU = TARGETS.cpuMSP430) & ~codeProc THEN
  917. check(MSP430.CheckProcDataSize(enter.param2 + proc._type.parSize, PROG.program.options.ram), pos1, 63);
  918. enter.param2 := enter.param2 * 65536 + line;
  919. enter.param3 := IL.codes.errlabels[10]
  920. END
  921. END;
  922. IF parser.sym = SCAN.lxEND THEN
  923. Next(parser);
  924. IF parser.sym = SCAN.lxIDENT THEN
  925. getpos(parser, pos);
  926. endname := parser.lex.ident;
  927. IF ~codeProc & (_import = NIL) THEN
  928. check(PROG.IdEq(endname, name), pos, 60);
  929. ExpectSym(parser, SCAN.lxSEMI);
  930. Next(parser)
  931. ELSE
  932. IF PROG.IdEq(endname, parser.unit.name) THEN
  933. ExpectSym(parser, SCAN.lxPOINT);
  934. Next(parser);
  935. endmod := TRUE
  936. ELSIF PROG.IdEq(endname, name) THEN
  937. ExpectSym(parser, SCAN.lxSEMI);
  938. Next(parser)
  939. ELSE
  940. error(pos, 60)
  941. END
  942. END
  943. ELSIF parser.sym = SCAN.lxSEMI THEN
  944. Next(parser)
  945. ELSE
  946. checklex(parser, SCAN.lxIDENT)
  947. END
  948. END;
  949. PROG.closeScope(unit);
  950. RETURN endmod
  951. END ProcDeclaration;
  952. BEGIN
  953. IF parser.sym = SCAN.lxCONST THEN
  954. Next(parser);
  955. WHILE parser.sym = SCAN.lxIDENT DO
  956. ConstTypeDeclaration(parser, TRUE)
  957. END
  958. END;
  959. IF parser.sym = SCAN.lxTYPE THEN
  960. Next(parser);
  961. WHILE parser.sym = SCAN.lxIDENT DO
  962. ConstTypeDeclaration(parser, FALSE)
  963. END
  964. END;
  965. ptr := PROG.linkPtr(parser.unit);
  966. IF ptr # NIL THEN
  967. pos.line := ptr.pos.line;
  968. pos.col := ptr.pos.col;
  969. pos.parser := parser;
  970. IF ptr.notRecord THEN
  971. error(pos, 58)
  972. ELSE
  973. error(pos, 48)
  974. END
  975. END;
  976. IF parser.sym = SCAN.lxVAR THEN
  977. Next(parser);
  978. IF parser.sym = SCAN.lxIDENT THEN
  979. VarDeclaration(parser)
  980. END
  981. END;
  982. endmod := FALSE;
  983. WHILE ~endmod & (parser.sym = SCAN.lxPROCEDURE) DO
  984. Next(parser);
  985. endmod := ProcDeclaration(parser)
  986. END
  987. RETURN endmod
  988. END DeclarationSequence;
  989. PROCEDURE parse (parser: PARSER);
  990. VAR
  991. unit: PROG.UNIT;
  992. label: INTEGER;
  993. name: INTEGER;
  994. endmod: BOOLEAN;
  995. errlabel: INTEGER;
  996. errno: INTEGER;
  997. ident: PROG.IDENT;
  998. BEGIN
  999. ASSERT(parser # NIL);
  1000. ASSERT(parser.scanner # NIL);
  1001. ExpectSym(parser, SCAN.lxMODULE);
  1002. ExpectSym(parser, SCAN.lxIDENT);
  1003. IF ~parser.main THEN
  1004. check1(parser.lex.ident.s = parser.modname, parser, 23)
  1005. END;
  1006. unit := PROG.newUnit(parser.lex.ident);
  1007. unit.fname := parser.fname;
  1008. parser.unit := unit;
  1009. ExpectSym(parser, SCAN.lxSEMI);
  1010. Next(parser);
  1011. IF parser.sym = SCAN.lxIMPORT THEN
  1012. ImportList(parser)
  1013. END;
  1014. INC(modules);
  1015. CONSOLE.String("compiling ");
  1016. CONSOLE.String("("); CONSOLE.Int(modules); CONSOLE.String(") ");
  1017. CONSOLE.String(unit.name.s);
  1018. IF unit.sysimport THEN
  1019. CONSOLE.String(" (SYSTEM)")
  1020. END;
  1021. CONSOLE.Ln;
  1022. IF PROG.program.options.uses THEN
  1023. ident := unit.idents.first(PROG.IDENT);
  1024. WHILE ident # NIL DO
  1025. IF (ident.typ = PROG.idMODULE) & (ident.unit # PROG.program.sysunit) THEN
  1026. CONSOLE.String(" "); CONSOLE.String(ident.unit.fname); CONSOLE.Ln
  1027. END;
  1028. ident := ident.next(PROG.IDENT)
  1029. END;
  1030. CONSOLE.Ln
  1031. END;
  1032. IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN
  1033. IL.fname(parser.fname)
  1034. END;
  1035. label := IL.NewLabel();
  1036. IL.Jmp(IL.opJMP, label);
  1037. name := IL.putstr(unit.name.s);
  1038. errlabel := IL.NewLabel();
  1039. IL.SetLabel(errlabel);
  1040. IL.StrAdr(name);
  1041. IL.Param1;
  1042. IL.AddCmd(IL.opPUSHC, modules);
  1043. IL.AddCmd0(IL.opERR);
  1044. FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO
  1045. IL.SetErrLabel(errno);
  1046. IL.AddCmd(IL.opPUSHC, errno);
  1047. IL.Jmp(IL.opJMP, errlabel)
  1048. END;
  1049. endmod := DeclarationSequence(parser);
  1050. IL.SetLabel(label);
  1051. IF ~endmod THEN
  1052. IF parser.sym = SCAN.lxBEGIN THEN
  1053. Next(parser);
  1054. parser.StatSeq(parser)
  1055. END;
  1056. checklex(parser, SCAN.lxEND);
  1057. ExpectSym(parser, SCAN.lxIDENT);
  1058. check1(parser.lex.ident.s = unit.name.s, parser, 25);
  1059. ExpectSym(parser, SCAN.lxPOINT)
  1060. END;
  1061. INC(lines, parser.lex.pos.line);
  1062. PROG.closeUnit(unit)
  1063. END parse;
  1064. PROCEDURE open (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN;
  1065. BEGIN
  1066. ASSERT(parser # NIL);
  1067. STRINGS.append(parser.fname, modname);
  1068. STRINGS.append(parser.fname, FileExt);
  1069. STRINGS.append(parser.modname, modname);
  1070. parser.scanner := SCAN.open(parser.fname)
  1071. RETURN parser.scanner # NIL
  1072. END open;
  1073. PROCEDURE NewParser (): PARSER;
  1074. VAR
  1075. pars: PARSER;
  1076. citem: C.ITEM;
  1077. BEGIN
  1078. citem := C.pop(parsers);
  1079. IF citem = NIL THEN
  1080. NEW(pars)
  1081. ELSE
  1082. pars := citem(PARSER)
  1083. END
  1084. RETURN pars
  1085. END NewParser;
  1086. PROCEDURE create* (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER;
  1087. VAR
  1088. parser: PARSER;
  1089. BEGIN
  1090. parser := NewParser();
  1091. parser.path := path;
  1092. parser.lib_path := lib_path;
  1093. parser.ext := UTILS.FILE_EXT;
  1094. parser.fname := path;
  1095. parser.modname := "";
  1096. parser.scanner := NIL;
  1097. parser.unit := NIL;
  1098. parser.constexp := FALSE;
  1099. parser.main := FALSE;
  1100. parser.open := open;
  1101. parser.parse := parse;
  1102. parser.StatSeq := StatSeq;
  1103. parser.expression := expression;
  1104. parser.designator := designator;
  1105. parser.chkreturn := chkreturn;
  1106. parser.create := create
  1107. RETURN parser
  1108. END create;
  1109. PROCEDURE init* (options: PROG.OPTIONS);
  1110. BEGIN
  1111. PROG.create(options);
  1112. parsers := C.create();
  1113. lines := 0;
  1114. modules := 0
  1115. END init;
  1116. END PARS.