TOYLAN.RIG 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #TOYLAN_COMPILER
  2. OPEN REP ' '; --message file is connected with the screen
  3. $LEXEMS:=#CALL_PAS(35 'A.TOY');
  4. -- a list of tokens is loaded from the file A.TOY by scanner
  5. $S_TREE := #A_PROGRAM($LEXEMS);
  6. -- 1st phase; result of parsing - abstract syntax tree - is
  7. -- imbedded in the variable $S_TREE; during parsing messages
  8. -- about discovered errors in file REP can be output.
  9. IF $S_TREE -> OPEN GEN 'A.BAL'; -- if the tree is created,
  10. -- then file is opened to output the generated BAL text
  11. #G_PROGRAM($S_TREE); -- 2nd phase-code generation
  12. #INTERPRETER($S_TREE) -- 2nd phase-code interpretation
  13. ELSIF T -> REP << errors are discovered FI;
  14. REP << end ##
  15. #A_PROGRAM -- the rule is applied to the list of tokens
  16. (. PROGRAM $Id
  17. (* $DECL++:= #A_DECLARATION ';' *)
  18. --formation of variables table
  19. (+ $STATEMENTS !.:= #A_STATEMENT + ';' )
  20. --formation of statements list
  21. .) / RETURN 'PROGRAM' :: <. NAME : $Id,
  22. DECLARATIONS : $DECL ,
  23. STATEMENTS : $STATEMENTS .>/ ##
  24. #A_DECLARATION $TYPE := ( INTEGER ! BOOLEAN )
  25. (+ $Id /IF LAST #A_PROGRAM $DECL.$Id OR $REZ.$Id ->
  26. REP << VARIABLE $Id DOUBLE DEFINED FI;
  27. $REZ++:= <.$Id : $TYPE .>/ + ',' ) / RETURN $REZ / ##
  28. #A_STATEMENT $REZ := ( #A_ASSIGNMENT ! #A_INPUT !
  29. #A_OUTPUT ! #A_CONDITIONAL ) / RETURN $REZ / ;;
  30. (* $A!.:=S'($$ <> ';' ) *) -- skip until nearest ';'
  31. / REP << UNRECOGNIZED STATEMENT $A /
  32. ##
  33. #A_ASSIGNMENT $Id ':='/ $LPType := LAST #A_PROGRAM $DECL .$Id;
  34. IF NOT $LPType -> REP << VARIABLE $Id 'IS NOT DEFINED' FI /
  35. $E:= #A_EXPRESSION
  36. /IF $LPType <> $E . TYPE ->
  37. REP<< 'LEFT AND RIGHT SIDE TYPES ARE DIFFERENT '
  38. 'IN ASSIGNMENT STATEMENT ' FI;
  39. RETURN ASSIGNMENT::<. LEFT: $Id, RIGHT: $E .> /
  40. ONFAIL IF $LPType -> REP<< 'WRONG EXPRESSION IN ASSIGNMENT' FI ##
  41. #A_INPUT GET '('
  42. (+ $E !.:= $Id /IF LAST #A_PROGRAM $DECL.$Id <> INTEGER ->
  43. REP << $Id 'IN STATEMENT GET IS NOT OF THE TYPE INTEGER'
  44. FI / + ',' ) ')' / RETURN INPUT :: $E / ##
  45. #A_OUTPUT PUT '(' (+ $C := #A_EXPRESSION / $E !.:= $C;
  46. IF $C . TYPE <> INTEGER ->
  47. REP << 'OPERAND OF PUT STATEMENT IS NOT OF THE TYPE INTEGER'
  48. FI / + ',' ) ')'/ RETURN OUTPUT :: $E / ##
  49. #A_CONDITIONAL 'IF' $BE := #A_EXPRESSION
  50. /IF $BE . TYPE <> BOOLEAN ->
  51. REP<< 'CONDITION IS NOT OF BOOLEAN TYPE' FI /
  52. 'THEN' (+ $P1 !.:= #A_STATEMENT + ';' )
  53. [ 'ELSE' (+ $P2 !.:= #A_STATEMENT + ';' ) ] 'FI'
  54. / RETURN CONDITIONAL :: <. COND : $BE , THEN : $P1 ,
  55. ELSE : $P2 .> / ##
  56. #A_EXPRESSION $A := #A_SUM [ '=' $B := #A_SUM
  57. / $A := COMPARE::<. ARG1 : $A, ARG2 : $B, TYPE : BOOLEAN.>/ ]
  58. / RETURN $A / ##
  59. #A_SUM $A := #A_FACTOR (* '+' $B := #A_FACTOR
  60. / $A := ADD::<. ARG1: $A, ARG2: $B, TYPE: INTEGER .>/ *)
  61. / RETURN $A / ##
  62. #A_FACTOR $A := #A_TERM (* '*' $B := #A_TERM
  63. /$A := MULT::<. ARG1: $A, ARG2: $B, TYPE: INTEGER .>/ *)
  64. / RETURN $A / ##
  65. #A_TERM
  66. $N / RETURN <. CONSTANT : $N , TYPE : INTEGER .>/;;
  67. ( ( TRUE / $K :=1/ ) ! ( FALSE / $K :=0 / ) )
  68. /RETURN <. CONSTANT: $K, TYPE: BOOLEAN .>/ ;;
  69. $Id / $X:= LAST #A_PROGRAM $DECL.$Id;
  70. IF NOT $X -> REP << VARIABLE $Id IS NOT DECLARED
  71. ELSIF T -> RETURN <. VARIABLE: $Id, TYPE: $X .> FI / ;;
  72. '(' $E := #A_EXPRESSION ')' / RETURN $E / ##
  73. #INTERPRETER
  74. $P
  75. / $++:= <. VARIABLES : #CREATE_TABLE ($P.DECLARATIONS) .>;
  76. --PRINT $;
  77. #I_PROGRAM ($);
  78. PRINT $.VARIABLES;
  79. /
  80. ##
  81. #CREATE_TABLE
  82. <* $Id : $Type / $Y ++ := <. $Id : 0 .> / *>
  83. / RETURN $Y /
  84. ##
  85. #I_PROGRAM
  86. <. STATEMENTS : #I_STATEMENTS .>
  87. ##
  88. #I_STATEMENTS (. (* #I_STATEMENT
  89. / PRINT LAST #INTERPRETER $.VARIABLES;
  90. #CALL_PAS(1) /
  91. *) .) ##
  92. #I_STATEMENT
  93. ( #I_INPUT ! #I_OUTPUT ! #I_ASSIGNMENT ! #I_CONDITIONAL ) ##
  94. #I_INPUT
  95. INPUT :: (. (* $Id
  96. /
  97. LAST #INTERPRETER $.VARIABLES.$Id:=
  98. #CALL_PAS(1 'toylan>') /
  99. *) .)
  100. ##
  101. #I_OUTPUT
  102. OUTPUT :: (. (* $E:= #I_EXPRESSION
  103. / REP << $E /
  104. *) .)
  105. ##
  106. #I_ASSIGNMENT
  107. ASSIGNMENT :: <. LEFT : $Id,
  108. RIGHT : $R:=#I_EXPRESSION
  109. .>
  110. / LAST #INTERPRETER $.VARIABLES.$Id:=$R/
  111. ##
  112. #I_CONDITIONAL
  113. CONDITIONAL :: <. COND : $E:=#I_EXPRESSION .>
  114. / IF $E<>0 -> #I_STATEMENTS ($.THEN)
  115. ELSIF $.ELSE -> #I_STATEMENTS ($.ELSE)
  116. FI /
  117. ##
  118. #I_EXPRESSION
  119. <. CONSTANT : $N .> / RETURN $N /;;
  120. <. VARIABLE : $Id .>
  121. / RETURN LAST #INTERPRETER $.VARIABLES.$Id/;;
  122. ADD:: <. ARG1 : $E1:=#I_EXPRESSION,
  123. ARG2 : $E2:=#I_EXPRESSION
  124. .>
  125. / RETURN $E1+$E2 /;;
  126. MULT:: <. ARG1 : $E1:=#I_EXPRESSION,
  127. ARG2 : $E2:=#I_EXPRESSION
  128. .>
  129. / RETURN $E1*$E2 /;;
  130. COMPARE:: <. ARG1 : $E1:=#I_EXPRESSION,
  131. ARG2 : $E2:=#I_EXPRESSION
  132. .> / IF $E1=$E2 -> RETURN 1
  133. ELSIF T -> RETURN 0
  134. FI/ ##
  135. #G_PROGRAM / $LABEL := 0 / --global variable $LABEL serves
  136. --to generate unique labels.
  137. PROGRAM::<.DECLARATIONS: $TAB := #TABLE_OF_NUMBERS,
  138. --creation of the table of unique variable numbers
  139. STATEMENTS: (.(* #G_STATEMENT *).) / GEN << 'EOJ' /,
  140. DECLARATIONS : #G_DECLARATIONS .> ##
  141. #TABLE_OF_NUMBERS <* $Id: $TYPE /$N :=$N+1; $T++:=<. $Id: $N.>/ *>
  142. /RETURN $T/ ##
  143. #G_STATEMENT ( #G_ASSIGNMENT ! #G_INPUT !
  144. #G_OUTPUT ! #G_CONDITIONAL ) ##
  145. #G_ASSIGNMENT ASSIGNMENT::<. LEFT: $Id := #NAME,
  146. RIGHT :( ( <. VARIABLE: $Id1:=#NAME .>
  147. /GEN << MOV @ $Id1 ',' $Id / ) !
  148. ( <. CONSTANT : $N .> /GEN << MOV @ '=' $N ',' $Id /) !
  149. ( $NREG := #G_EXPRESSION
  150. /GEN << 'SAVE' @ 'R' $NREG ',' $Id / ) ) .> ##
  151. #G_INPUT INPUT::(. (* $Id := #NAME /GEN << READ $Id / *) .) ##
  152. #G_OUTPUT OUTPUT :: (. (*
  153. ( ( <. VARIABLE : $Id := #NAME .> /GEN << WRITE $Id / ) !
  154. ( <. CONSTANT : $N .> /GEN << WRITE @ '=' $N / ) !
  155. ( $NREG := #G_EXPRESSION /GEN << WRITE @ 'R' $NREG /) )
  156. *) .) ##
  157. #G_CONDITIONAL CONDITIONAL ::
  158. <. COND : $NREG := #G_EXPRESSION
  159. / $LABEL1 :=#NEW_LABEL(); $LABEL2 :=#NEW_LABEL() /,
  160. THEN : / GEN << BRANCH @ 'R' $NREG ',L' $LABEL1 /
  161. (. (* #G_STATEMENT *) .)
  162. / IF $.ELSE -> GEN << JUMP @ 'L' $LABEL2 FI;
  163. GEN << @ 'L' $LABEL1 ': NOP' / ,
  164. [ ELSE : (. (* #G_STATEMENT *) .)
  165. / GEN << @ 'L' $LABEL2 ': NOP' / ] .> ##
  166. #G_EXPRESSION --returns the number of the register containing
  167. --result of the evaluation of expression
  168. $EXPR
  169. / $NREG := 0 / -- number of the first accessible register
  170. /RETURN #G_EXPR($EXPR)/
  171. ##
  172. #G_EXPR ( <. VARIABLE: $ID :=#NAME .> !
  173. <. CONSTANT: $N / $ID := #IMPLODE('=' $N)/ .>)
  174. / $REG := COPY( LAST #G_EXPRESSION $NREG ) ;
  175. GEN << 'LOAD' @ 'R' $REG ',' $ID ;
  176. LAST #G_EXPRESSION $NREG + := 1; RETURN $REG / ;;
  177. $OP::<. ARG1 : $R1 := #G_EXPR, ARG2 : $R2 := #G_EXPR .>
  178. / GEN << $OP @ 'R' $R1 ',R' $R2 ; RETURN $R1 / ##
  179. #G_DECLARATIONS
  180. <* $ID: $TYPE /$ID1 := #NAME($ID); GEN<< $ID1 ':' DEFWORD 0 /*> ##
  181. #NEW_LABEL --auxiliary rule
  182. /LAST #G_PROGRAM $LABEL+:=1;
  183. RETURN COPY (LAST #G_PROGRAM $LABEL )/ ##
  184. #NAME $ID --returns standard name of the variable $ID in $TAB
  185. / RETURN #IMPLODE( VAR LAST #G_PROGRAM $TAB.$ID)/ ##