Scanner.Mod 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. MODULE Scanner;
  2. IMPORT Out, Files;
  3. CONST
  4. (*Лексемы*)
  5. null = 0; times* = 1; rdiv* = 2; div* = 3; mod* = 4;
  6. and* = 5; plus* = 6; minus* = 7; or* = 8; eql* = 9;
  7. neq* = 10; lss* = 11; leq* = 12; gtr* = 13; geq* = 14;
  8. in* = 15; is* = 16; arrow* = 17; period* = 18;
  9. char* = 20; int* = 21; real* = 22; false* = 23; true* = 24;
  10. nil* = 25; string* = 26; not* = 27; lparen* = 28; lbrak* = 29;
  11. lbrace* = 30; ident* = 31;
  12. if* = 32; while* = 34; repeat* = 35; case* = 36; for* = 37;
  13. comma* = 40; colon* = 41; becomes* = 42; upto* = 43; rparen* = 44;
  14. rbrak* = 45; rbrace* = 46; then* = 47; of* = 48; do* = 49;
  15. to* = 50; by* = 51; semicolon* = 52; end* = 53; bar* = 54;
  16. else* = 55; elsif* = 56; until* = 57; return* = 58;
  17. array* = 60; record* = 61; pointer* = 62; const* = 63; type* = 64;
  18. var* = 65; procedure* = 66; begin* = 67; import* = 68; module* = 69;
  19. eot = 70;
  20. VAR r: Files.Rider;
  21. ch: CHAR;
  22. id*: ARRAY 32 OF CHAR;
  23. idlen*: INTEGER;
  24. ival*: INTEGER;
  25. sval*: ARRAY 1024 OF CHAR;
  26. slen*: INTEGER;
  27. error*: BOOLEAN;
  28. PROCEDURE Color(n: INTEGER);
  29. BEGIN
  30. Out.Char(CHR(27)); Out.Char("[");
  31. Out.Int(n, 0); Out.Char("m")
  32. END Color;
  33. PROCEDURE Mark*(msg: ARRAY OF CHAR);
  34. BEGIN
  35. error := TRUE;
  36. Color(41); Color(97);
  37. Out.String("Ошибка на поз. ");
  38. Out.Int(SHORT(Files.Pos(r)), 0);
  39. Out.String(": "); Out.String(msg);
  40. Out.Char("."); Color(0); Out.Ln
  41. END Mark;
  42. PROCEDURE ReadCh;
  43. BEGIN
  44. IF r.eof THEN ch := 0X
  45. ELSE Files.Read(r, ch)
  46. END
  47. END ReadCh;
  48. PROCEDURE Get*(VAR sym: INTEGER);
  49. VAR d: ARRAY 30 OF INTEGER; (*digits*)
  50. i, dlen, base: INTEGER;
  51. BEGIN
  52. WHILE (ch # 0X) & (ch <= " ") DO
  53. ReadCh
  54. END;
  55. IF r.eof THEN sym := eot
  56. ELSIF ch = "," THEN sym := comma; ReadCh
  57. ELSIF ch = "." THEN sym := period; ReadCh
  58. ELSIF ch = ";" THEN sym := semicolon; ReadCh
  59. ELSIF ch = "+" THEN sym := plus; ReadCh
  60. ELSIF ch = "-" THEN sym := minus; ReadCh
  61. ELSIF ch = "*" THEN sym := times; ReadCh
  62. ELSIF ch = "/" THEN sym := rdiv; ReadCh
  63. ELSIF ch = "&" THEN sym := and; ReadCh
  64. ELSIF ch = "~" THEN sym := not; ReadCh
  65. ELSIF ch = "(" THEN sym := lparen; ReadCh
  66. ELSIF ch = ")" THEN sym := rparen; ReadCh
  67. ELSIF ch = "[" THEN sym := lbrak; ReadCh
  68. ELSIF ch = "]" THEN sym := rbrak; ReadCh
  69. ELSIF ch = "{" THEN sym := lbrace; ReadCh
  70. ELSIF ch = "}" THEN sym := rbrace; ReadCh
  71. ELSIF ch = "=" THEN sym := eql; ReadCh
  72. ELSIF ch = "#" THEN sym := neq; ReadCh
  73. ELSIF ch = "<" THEN ReadCh;
  74. IF ch = "=" THEN sym := leq; ReadCh
  75. ELSE sym := lss
  76. END
  77. ELSIF ch = ">" THEN ReadCh;
  78. IF ch = "=" THEN sym := geq; ReadCh
  79. ELSE sym := gtr
  80. END
  81. ELSIF ch = ":" THEN
  82. ReadCh;
  83. IF ch = "=" THEN sym := becomes; ReadCh
  84. ELSE sym := colon
  85. END
  86. ELSIF ("A" <= ch) & (ch <= "Z") OR ("a" <= ch) & (ch <= "z") THEN
  87. id[0] := ch; idlen := 1; ReadCh;
  88. WHILE ("A" <= ch) & (ch <= "Z") OR
  89. ("a" <= ch) & (ch <= "z") OR
  90. ("0" <= ch) & (ch <= "9") DO
  91. IF idlen < LEN(id) - 1 THEN
  92. id[idlen] := ch;
  93. INC(idlen)
  94. END;
  95. ReadCh
  96. END;
  97. id[idlen] := 0X;
  98. IF id = "MODULE" THEN sym := module
  99. ELSIF id = "IMPORT" THEN sym := import
  100. ELSIF id = "CONST" THEN sym := const
  101. ELSIF id = "VAR" THEN sym := var
  102. ELSIF id = "BEGIN" THEN sym := begin
  103. ELSIF id = "END" THEN sym := end
  104. ELSIF id = "IF" THEN sym := if
  105. ELSIF id = "THEN" THEN sym := then
  106. ELSIF id = "ELSE" THEN sym := else
  107. ELSIF id = "ELSIF" THEN sym := elsif
  108. ELSIF id = "WHILE" THEN sym := while
  109. ELSIF id = "DIV" THEN sym := div
  110. ELSIF id = "MOD" THEN sym := mod
  111. ELSIF id = "OR" THEN sym := or
  112. ELSE sym := ident
  113. END
  114. ELSIF ("0" <= ch) & (ch <= "9") THEN
  115. d[0] := ORD(ch) - ORD("0"); ReadCh;
  116. dlen := 1;
  117. WHILE ("0" <= ch) & (ch <= "9") OR
  118. ("A" <= ch) & (ch <= "F") DO
  119. IF dlen < LEN(d) THEN
  120. IF ("0" <= ch) & (ch <= "9") THEN d[dlen] := ORD(ch) - ORD("0")
  121. ELSE d[dlen] := ORD(ch) - ORD("A") + 10
  122. END;
  123. INC(dlen)
  124. ELSE Mark("Слишком длинное число")
  125. END;
  126. ReadCh
  127. END;
  128. sym := int;
  129. IF (ch = "X") OR (ch = "H") THEN
  130. base := 16;
  131. IF ch = "X" THEN sym := char END;
  132. ReadCh
  133. ELSE base := 10
  134. END;
  135. ival := 0; i := 0;
  136. WHILE i < dlen DO
  137. IF (base = 10) & (d[i] >= 10) THEN
  138. Mark("Некорректное число")
  139. END;
  140. ival := ival * base + d[i];
  141. INC(i)
  142. END
  143. ELSIF ch = 22X THEN ReadCh; sym := string;
  144. slen := 0;
  145. WHILE (ch # 22X) & (ch >= " ") & (slen < LEN(sval) - 1) DO
  146. sval[slen] := ch;
  147. INC(slen);
  148. ReadCh
  149. END;
  150. IF ch = 0X THEN Mark("Неожиданный конец файла")
  151. ELSIF ch < " " THEN Mark("Недопустимая литера в строке")
  152. ELSIF ch # 22X THEN Mark("Слишком длинная строка")
  153. END;
  154. sval[slen] := 0X;
  155. (*Промотка до ближайшей кавычки*)
  156. WHILE (ch # 0X) & (ch # 22X) DO ReadCh END;
  157. ReadCh
  158. ELSE
  159. sym := null;
  160. ReadCh
  161. END
  162. END Get;
  163. PROCEDURE Init*(F: Files.File);
  164. BEGIN
  165. Files.Set(r, F, 0);
  166. ReadCh;
  167. error := FALSE
  168. END Init;
  169. END Scanner.