PARS.ob07 42 KB

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