SyntaxAnalysis.mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. IMPLEMENTATION MODULE SyntaxAnalysis; (* gf 27.04.89 (pl0) *)
  2. FROM SYSTEM IMPORT TSIZE;
  3. FROM Storage IMPORT ALLOCATE;
  4. FROM InOut IMPORT Write, WriteLn, WriteCard, WriteString;
  5. FROM Scanner IMPORT SYMBOL, IDENT, STRING, POSITION,
  6. sym, id, num, strp, pos,
  7. traceParser,
  8. InitScanner, GetSymbol;
  9. FROM InternalTree IMPORT BLCK, DECL, STMT, EXPR,
  10. blckPtr, declPtr, stmtPtr, exprPtr,
  11. declKind, stmtKind, exprKind,
  12. monOperator, dyOperator, conType,
  13. NewDeclSequence, NewStmtSequence, NewExprSequence,
  14. NoDeclaration, NoStatement, NoExpression;
  15. FROM ErrorHandling IMPORT PrintError1;
  16. PROCEDURE Trace (s : ARRAY OF CHAR);
  17. BEGIN
  18. IF traceParser THEN
  19. WriteString(' ');
  20. WriteString(s); WriteLn
  21. END
  22. END Trace;
  23. PROCEDURE Error(n : CARDINAL);
  24. VAR i : CARDINAL;
  25. BEGIN
  26. SyntaxError := TRUE;
  27. PrintError1(n , pos)
  28. END Error;
  29. PROCEDURE test(s : SYMBOL; n: CARDINAL);
  30. BEGIN
  31. IF sym = sEof THEN Error(31) END;
  32. IF sym < s THEN
  33. Error(n);
  34. Error(98);
  35. REPEAT
  36. GetSymbol;
  37. IF sym = sEof THEN Error(31) END;
  38. UNTIL sym >= s;
  39. Error(99)
  40. END;
  41. END test;
  42. PROCEDURE ErrorSkip(n: CARDINAL; s: SYMBOL);
  43. PROCEDURE Skip(s : SYMBOL);
  44. BEGIN
  45. IF sym = sEof THEN Error(31) END;
  46. IF sym < s THEN
  47. Error(98);
  48. REPEAT
  49. GetSymbol;
  50. IF sym = sEof THEN Error(31) END;
  51. UNTIL sym >= s;
  52. Error(99)
  53. END;
  54. END Skip;
  55. BEGIN
  56. Error(n);
  57. Skip(s)
  58. END ErrorSkip;
  59. PROCEDURE ApendDeclaration(VAR lastnode: declPtr; decl: declPtr);
  60. BEGIN
  61. IF lastnode^.first # NIL THEN
  62. lastnode^.rest := NewDeclSequence(pos);
  63. lastnode := lastnode^.rest;
  64. END;
  65. lastnode^.first := decl;
  66. END ApendDeclaration;
  67. (* the following forward declarations are needed for OSI M2 compiler
  68. ( *$nonstandard * )
  69. PROCEDURE Block () : blckPtr; FORWARD;
  70. PROCEDURE Expression () : exprPtr; FORWARD;
  71. PROCEDURE Variable (id: IDENT) : exprPtr; FORWARD;
  72. ( *$standard *)
  73. PROCEDURE Factor(): exprPtr;
  74. VAR f : exprPtr;
  75. lId : IDENT;
  76. BEGIN
  77. Trace( "Factor");
  78. test(sLParen, 6);
  79. NEW(f);
  80. WITH f^ DO
  81. CASE sym OF
  82. sIdent:
  83. Trace(" sIdent");
  84. lId := id;
  85. GetSymbol;
  86. f := Variable(lId)
  87. | sNumber:
  88. Trace(" sNumber");
  89. position := pos;
  90. kind := immediatevalue;
  91. immVal := num;
  92. immType := int;
  93. GetSymbol
  94. | sLParen:
  95. Trace(" sLParen");
  96. GetSymbol;
  97. f := Expression();
  98. IF sym = sRParen THEN
  99. GetSymbol
  100. ELSE
  101. ErrorSkip(7, sTimes)
  102. END
  103. | sEof:
  104. ELSE
  105. ErrorSkip(8, sTimes)
  106. END;
  107. END;
  108. RETURN f
  109. END Factor;
  110. PROCEDURE Term() : exprPtr;
  111. VAR t, t1 : exprPtr;
  112. BEGIN
  113. Trace( "Term");
  114. t := Factor();
  115. WHILE (sym = sTimes) OR (sym = sDiv) DO
  116. NEW(t1);
  117. WITH t1^ DO
  118. position := pos;
  119. kind := dyadic;
  120. IF sym = sTimes THEN
  121. dyOpr := times
  122. ELSE
  123. dyOpr := divides
  124. END;
  125. leftArg := t;
  126. GetSymbol;
  127. rightArg := Factor();
  128. END;
  129. t := t1;
  130. END;
  131. RETURN t
  132. END Term;
  133. PROCEDURE Expression(): exprPtr;
  134. VAR t, t1: exprPtr;
  135. BEGIN
  136. Trace( "Expression");
  137. IF sym = sMinus THEN
  138. NEW(t);
  139. WITH t^ DO
  140. position := pos;
  141. kind := monadic;
  142. monOpr := neg;
  143. GetSymbol;
  144. arg := Term();
  145. END
  146. ELSIF sym = sPlus THEN
  147. GetSymbol;
  148. t := Term();
  149. ELSE
  150. t := Term();
  151. END;
  152. WHILE (sym = sPlus) OR (sym = sMinus) DO
  153. NEW(t1);
  154. WITH t1^ DO
  155. position := pos;
  156. kind := dyadic;
  157. IF sym = sPlus THEN
  158. dyOpr := plus
  159. ELSE
  160. dyOpr := minus
  161. END;
  162. leftArg := t;
  163. GetSymbol;
  164. rightArg := Term();
  165. END;
  166. t := t1
  167. END;
  168. RETURN t
  169. END Expression;
  170. PROCEDURE Condition(): exprPtr;
  171. VAR c : exprPtr;
  172. BEGIN
  173. Trace( "Condition");
  174. NEW(c);
  175. WITH c^ DO
  176. position := pos;
  177. IF sym = sOdd THEN
  178. kind := monadic;
  179. monOpr := odd;
  180. GetSymbol;
  181. arg := Expression();
  182. ELSE
  183. kind := dyadic;
  184. leftArg := Expression();
  185. CASE sym OF
  186. sEQ : dyOpr := equal;
  187. | sNE : dyOpr := notequal;
  188. | sLT : dyOpr := less;
  189. | sGE : dyOpr := greaterequal;
  190. | sGT : dyOpr := greater;
  191. | sLE : dyOpr := lessequal;
  192. ELSE
  193. Error(28);
  194. RETURN c
  195. END;
  196. GetSymbol;
  197. rightArg := Expression();
  198. END
  199. END;
  200. RETURN c
  201. END Condition;
  202. PROCEDURE Variable(id: IDENT): exprPtr;
  203. VAR p : exprPtr;
  204. BEGIN
  205. Trace("Variable");
  206. NEW(p);
  207. WITH p^ DO
  208. position := pos;
  209. kind := identifier;
  210. usedId := id;
  211. usedInd := NoExpression();
  212. END;
  213. RETURN p
  214. END Variable;
  215. PROCEDURE String() : exprPtr;
  216. VAR p1 : exprPtr;
  217. BEGIN
  218. NEW(p1); p1^.position := pos;
  219. p1^.kind := string;
  220. p1^.stringPtr := strp;
  221. GetSymbol;
  222. RETURN p1
  223. END String;
  224. PROCEDURE Assign(id: IDENT; pos: POSITION): stmtPtr;
  225. VAR p : stmtPtr;
  226. BEGIN
  227. Trace("Assign");
  228. NEW(p);
  229. WITH p^ DO
  230. position := pos;
  231. kind := assign;
  232. target := Variable(id);
  233. IF (sym = sBecomes) OR (sym = sEQ) THEN
  234. position := pos;
  235. IF sym = sEQ THEN Error(13) END;
  236. GetSymbol;
  237. source := Expression()
  238. ELSE
  239. ErrorSkip(45, sEnd)
  240. END
  241. END;
  242. RETURN p
  243. END Assign;
  244. PROCEDURE Call(id: IDENT; pos: POSITION): stmtPtr;
  245. VAR callStmt : stmtPtr;
  246. parExpr : exprPtr;
  247. BEGIN
  248. Trace("Call");
  249. NEW(callStmt);
  250. WITH callStmt^ DO
  251. position := pos;
  252. kind := call;
  253. callId := id;
  254. END;
  255. RETURN callStmt
  256. END Call;
  257. PROCEDURE Statements(): stmtPtr;
  258. VAR stmts : stmtPtr;
  259. currStmt : stmtPtr;
  260. PROCEDURE Statement(): stmtPtr;
  261. VAR stmt : stmtPtr;
  262. currStmt : stmtPtr;
  263. lId : IDENT;
  264. lpos : POSITION;
  265. BEGIN
  266. Trace( "Statement");
  267. test(sIdent, 10);
  268. CASE sym OF
  269. sIdent:
  270. Trace(" sIdent");
  271. lId := id; lpos := pos;
  272. GetSymbol;
  273. stmt := Assign(lId, lpos);
  274. | sCall:
  275. Trace(" sCall");
  276. GetSymbol;
  277. IF sym = sIdent THEN
  278. lId := id; lpos := pos;
  279. GetSymbol;
  280. stmt := Call(lId, lpos);
  281. ELSE
  282. stmt := NoStatement();
  283. Error(29)
  284. END
  285. | sBegin:
  286. Trace(" sBegin");
  287. GetSymbol;
  288. stmt := NewStmtSequence(pos);
  289. currStmt := stmt;
  290. LOOP
  291. currStmt^.first := Statement();
  292. IF sym = sSemicolon THEN
  293. GetSymbol;
  294. IF currStmt^.first^.kind # nostatement THEN
  295. currStmt^.rest := NewStmtSequence(pos);
  296. currStmt := currStmt^.rest
  297. END
  298. ELSE
  299. IF sym = sEnd THEN
  300. GetSymbol
  301. ELSE
  302. Error(17)
  303. END;
  304. EXIT
  305. END
  306. END;
  307. currStmt^.rest := NoStatement();
  308. | sIf:
  309. Trace(" sIf");
  310. NEW(stmt);
  311. stmt^.position := pos;
  312. stmt^.kind := if;
  313. GetSymbol;
  314. stmt^.choice := Condition();
  315. IF sym = sThen THEN
  316. GetSymbol;
  317. stmt^.thenPart := Statement();
  318. stmt^.elsePart := NoStatement()
  319. ELSE
  320. ErrorSkip(16, sEnd)
  321. END
  322. | sWhile:
  323. Trace(" sWhile");
  324. NEW(stmt);
  325. stmt^.position := pos;
  326. stmt^.kind := while;
  327. GetSymbol;
  328. stmt^.stop := Condition();
  329. IF sym = sDo THEN
  330. GetSymbol
  331. ELSE
  332. Error(18)
  333. END;
  334. stmt^.doPart := Statement();
  335. | sRead:
  336. Trace(" sRead");
  337. GetSymbol;
  338. IF sym = sIdent THEN
  339. NEW(stmt);
  340. stmt^.position := pos;
  341. stmt^.kind := read;
  342. lId := id;
  343. GetSymbol;
  344. stmt^.inVar := Variable(lId);
  345. ELSE
  346. ErrorSkip(14, sEnd)
  347. END
  348. | sWrite:
  349. Trace(" sWrite");
  350. GetSymbol;
  351. NEW(stmt);
  352. stmt^.position := pos;
  353. stmt^.kind := write;
  354. IF sym = sString THEN
  355. stmt^.outVal := String()
  356. ELSE
  357. stmt^.outVal := Expression()
  358. END
  359. | sEof:
  360. | sEnd,
  361. sElse,
  362. sSemicolon:
  363. NEW(stmt);
  364. stmt^.position := pos;
  365. stmt^.kind := nostatement;
  366. ELSE
  367. ErrorSkip(32, sEnd)
  368. END;
  369. test(sEnd, 19);
  370. RETURN stmt
  371. END Statement;
  372. BEGIN (* Statements *)
  373. Trace('Statements');
  374. stmts := NewStmtSequence(pos);
  375. currStmt := stmts;
  376. LOOP
  377. currStmt^.first := Statement();
  378. IF sym = sSemicolon THEN
  379. GetSymbol;
  380. IF currStmt^.first^.kind # nostatement THEN
  381. currStmt^.rest := NewStmtSequence(pos);
  382. currStmt := currStmt^.rest
  383. END
  384. ELSE
  385. EXIT
  386. END
  387. END;
  388. currStmt^.rest := NoStatement();
  389. RETURN stmts
  390. END Statements;
  391. PROCEDURE ConstDeclaration(): declPtr;
  392. VAR Ident : IDENT;
  393. p : declPtr;
  394. BEGIN
  395. Trace( "ConstDeclaration");
  396. IF sym = sIdent THEN
  397. Ident := id;
  398. GetSymbol;
  399. IF (sym = sEQ) OR (sym = sBecomes) THEN
  400. IF sym = sBecomes THEN Error(1) END;
  401. GetSymbol;
  402. IF sym = sNumber THEN
  403. NEW(p); p^.position := pos;
  404. p^.kind := constdecl;
  405. p^.constVal := num;
  406. p^.constId := Ident;
  407. GetSymbol;
  408. RETURN p
  409. ELSE ErrorSkip(2, sSemicolon)
  410. END
  411. ELSE ErrorSkip(3, sSemicolon)
  412. END
  413. ELSE ErrorSkip(4, sSemicolon)
  414. END;
  415. RETURN NoDeclaration();
  416. END ConstDeclaration;
  417. PROCEDURE VarDeclaration(type: declPtr) : declPtr;
  418. VAR p : declPtr;
  419. BEGIN
  420. Trace( "VarDeclaration");
  421. IF sym = sIdent THEN
  422. NEW(p); p^.position := pos;
  423. p^.kind := vardecl;
  424. p^.varId := id;
  425. p^.varType := type;
  426. GetSymbol;
  427. RETURN p
  428. ELSE
  429. ErrorSkip(4, sSemicolon)
  430. END;
  431. RETURN NoDeclaration();
  432. END VarDeclaration;
  433. PROCEDURE ProcDeclaration(): declPtr;
  434. VAR proc : declPtr;
  435. BEGIN
  436. NEW(proc); proc^.position := pos;
  437. proc^.kind := procdecl;
  438. proc^.procId := id;
  439. GetSymbol;
  440. IF sym = sSemicolon THEN
  441. GetSymbol
  442. ELSE
  443. ErrorSkip(5, sBegin)
  444. END;
  445. proc^.body := Block();
  446. RETURN proc;
  447. END ProcDeclaration;
  448. PROCEDURE Block() : blckPtr;
  449. VAR root : blckPtr;
  450. decl : declPtr;
  451. lastdecl : declPtr;
  452. type : declPtr;
  453. PROCEDURE Declarations;
  454. BEGIN
  455. LOOP
  456. CASE sym OF
  457. sConst:
  458. GetSymbol;
  459. LOOP
  460. ApendDeclaration(lastdecl, ConstDeclaration());
  461. IF sym = sComma THEN
  462. GetSymbol
  463. ELSIF sym = sSemicolon THEN
  464. GetSymbol; EXIT
  465. ELSE
  466. ErrorSkip(5, sBegin); EXIT
  467. END;
  468. END
  469. |sVar:
  470. GetSymbol;
  471. NEW(type);
  472. LOOP
  473. ApendDeclaration(lastdecl, VarDeclaration(type));
  474. IF sym = sComma THEN
  475. GetSymbol
  476. ELSIF sym = sColon THEN
  477. GetSymbol;
  478. IF sym = sIdent THEN
  479. type^.position := pos;
  480. type^.kind := typeident;
  481. type^.typeId := id;
  482. GetSymbol
  483. ELSE
  484. ErrorSkip(37, sBegin)
  485. END;
  486. IF sym = sSemicolon THEN
  487. GetSymbol
  488. ELSE
  489. Error(36)
  490. END;
  491. EXIT
  492. ELSE
  493. ErrorSkip(36, sBegin); EXIT
  494. END;
  495. END;
  496. |sProcedure:
  497. GetSymbol;
  498. IF sym = sIdent THEN
  499. ApendDeclaration(lastdecl, ProcDeclaration());
  500. ELSE
  501. ErrorSkip(4, sSemicolon)
  502. END;
  503. IF sym = sSemicolon THEN
  504. GetSymbol
  505. ELSE
  506. ErrorSkip(5, sBegin)
  507. END
  508. ELSE
  509. EXIT (* loop *)
  510. END;
  511. END; (* loop *)
  512. END Declarations;
  513. BEGIN (* Block *)
  514. Trace( "Block");
  515. decl := NewDeclSequence(pos); lastdecl := decl;
  516. Declarations;
  517. test(sBegin, 33);
  518. WHILE (sym # sBegin) AND (sym # sEof) DO
  519. Declarations;
  520. test(sBegin, 33)
  521. END;
  522. IF lastdecl^.first = NIL THEN
  523. lastdecl^.first := NoDeclaration()
  524. END;
  525. lastdecl^.rest := NoDeclaration();
  526. NEW(root); root^.position := pos;
  527. root^.declarations := decl;
  528. IF sym = sBegin THEN
  529. GetSymbol;
  530. root^.statements := Statements();
  531. IF sym = sEnd THEN
  532. GetSymbol
  533. ELSE
  534. ErrorSkip(17, sBegin)
  535. END
  536. ELSE
  537. ErrorSkip(33, sBegin)
  538. END;
  539. RETURN root
  540. END Block;
  541. PROCEDURE parse(): blckPtr;
  542. VAR root : blckPtr;
  543. BEGIN
  544. SyntaxError := FALSE;
  545. InitScanner;
  546. GetSymbol;
  547. root := Block();
  548. IF sym # sPeriod THEN ErrorSkip(9, sEof) END;
  549. RETURN root
  550. END parse;
  551. BEGIN
  552. END SyntaxAnalysis.