fork(2) download
  1. import java.io.*
  2.  
  3. // Компилятор языка "О"
  4.  
  5. fun main(args:Array<String>) {
  6. Main.main(args)
  7. }
  8.  
  9.  
  10. object Main {
  11. internal fun Init() {
  12. Text.Reset()
  13. if (!Text.Ok)
  14. Error.Message(Text.Message)
  15. Scan.Init()
  16. Gen.Init()
  17. }
  18.  
  19. internal fun Done() {
  20. Text.Close()
  21. }
  22.  
  23. @JvmStatic fun main(args:Array<String>) {
  24. println("\nКомпилятор языка О")
  25. if (args.size == 0)
  26. Location.Path = ""
  27. else
  28. Location.Path = args[0]
  29. Init() // Инициализация
  30. Pars.Compile() // Компиляция
  31. OVM.Run() // Выполнение
  32. Done() // Завершение
  33. }
  34. }
  35.  
  36. // Текущая позиция в исходном тексте
  37. internal object Location {
  38. var Line:Int = 0 // Номер строки
  39. var Pos:Int = 0 // Номер символа в строке
  40. var LexPos:Int = 0 // Позиция начала лексемы
  41. var Path:String = ""// Путь к файлу
  42. }
  43.  
  44. // Обработка ошибок
  45. internal object Error {
  46. fun Message(Msg:String) {
  47. val ELine = Location.Line
  48. while (Text.Ch != Text.chEOL && Text.Ch != Text.chEOT)
  49. Text.NextCh()
  50. if (Text.Ch == Text.chEOT)
  51. println()
  52. for (i in 1 until Location.LexPos)
  53. print(' ')
  54. println("^\n(Строка $ELine) Ошибка: $Msg\n")
  55. print("Нажмите ВВОД")
  56. try
  57. {
  58. while (System.`in`.read() != '\n'.toInt()) ;
  59. }
  60. catch (e:IOException) {}
  61. System.exit(0)
  62. }
  63.  
  64. fun Expected(Msg:String) {
  65. Message("Ожидается " + Msg)
  66. }
  67.  
  68. fun Warning(Msg:String) {
  69. println()
  70. println("Предупреждение: " + Msg)
  71. }
  72.  
  73. }
  74.  
  75.  
  76. // Генератор кода
  77. internal object Gen {
  78. var PC:Int = 0
  79.  
  80. fun Init() {
  81. PC = 0
  82. }
  83.  
  84. fun Cmd(Cmd:Int) {
  85. if (PC < OVM.MEMSIZE)
  86. OVM.M[PC++] = Cmd
  87. else
  88. Error.Message("Недостаточно памяти для кода")
  89. }
  90.  
  91. fun Fixup(a:Int) {
  92. var A = a
  93. while (A > 0)
  94. {
  95. val temp = OVM.M[A - 2]
  96. OVM.M[A - 2] = PC
  97. A = temp
  98. }
  99. }
  100.  
  101. fun Abs() {
  102. Cmd(OVM.cmDup)
  103. Cmd(0)
  104. Cmd(PC + 3)
  105. Cmd(OVM.cmIfGE)
  106. Cmd(OVM.cmNeg)
  107. }
  108.  
  109. fun Min() {
  110. Cmd(Integer.MAX_VALUE)
  111. Cmd(OVM.cmNeg)
  112. Cmd(1)
  113. Cmd(OVM.cmSub)
  114. }
  115.  
  116. fun Odd() {
  117. Cmd(2)
  118. Cmd(OVM.cmMod)
  119. Cmd(1)
  120. Cmd(0) // Адрес перехода вперед
  121. Cmd(OVM.cmIfNE)
  122. }
  123.  
  124. fun Const(C:Int) {
  125. Cmd(Math.abs(C))
  126. if (C < 0)
  127. Cmd(OVM.cmNeg)
  128. }
  129.  
  130. fun Comp(Lex:Int) {
  131. Cmd(0) // Адрес перехода вперед
  132. when (Lex) {
  133. Scan.lexEQ -> Cmd(OVM.cmIfNE)
  134. Scan.lexNE -> Cmd(OVM.cmIfEQ)
  135. Scan.lexLE -> Cmd(OVM.cmIfGT)
  136. Scan.lexLT -> Cmd(OVM.cmIfGE)
  137. Scan.lexGE -> Cmd(OVM.cmIfLT)
  138. Scan.lexGT -> Cmd(OVM.cmIfLE)
  139. }
  140. }
  141.  
  142. fun Addr(X:Obj) {
  143. Cmd(X.Val) // В текущую ячейку адрес предыдущей + 2
  144. X.Val = PC + 1 // Адрес+2 = PC+1
  145. }
  146.  
  147. fun AllocateVariables() {
  148. var VRef: Obj? // Ссылка на переменную в таблице имен
  149. VRef = Table.FirstVar() // Найти первую переменную
  150. while (VRef != null) {
  151. if (VRef.Val == 0)
  152. Error.Warning("Переменная " + VRef.Name + " не используется")
  153. else if (PC < OVM.MEMSIZE) {
  154. Fixup(VRef.Val) // Адресная привязка переменной
  155. PC++
  156. }
  157. else
  158. Error.Message("Недостаточно памяти для переменных")
  159. VRef = Table.NextVar() // Найти следующую переменную
  160. }
  161. }
  162. }
  163.  
  164. // Виртуальная машина
  165. internal object OVM {
  166. val MEMSIZE = 8*1024
  167. val cmStop = -1
  168. val cmAdd = -2
  169. val cmSub = -3
  170. val cmMult = -4
  171. val cmDiv = -5
  172. val cmMod = -6
  173. val cmNeg = -7
  174. val cmLoad = -8
  175. val cmSave = -9
  176. val cmDup = -10
  177. val cmDrop = -11
  178. val cmSwap = -12
  179. val cmOver = -13
  180. val cmGOTO = -14
  181. val cmIfEQ = -15
  182. val cmIfNE = -16
  183. val cmIfLE = -17
  184. val cmIfLT = -18
  185. val cmIfGE = -19
  186. val cmIfGT = -20
  187. val cmIn = -21
  188. val cmOut = -22
  189. val cmOutLn = -23
  190.  
  191. var M = IntArray(MEMSIZE)
  192.  
  193. private val input = StreamTokenizer(InputStreamReader(System.`in`))
  194.  
  195. fun readln() {
  196. try {
  197. while (System.`in`.read() != '\n'.toInt()) ;
  198. }
  199. catch (e:IOException) {}
  200. }
  201.  
  202. fun ReadInt():Int {
  203. try {
  204. input.nextToken()
  205. }
  206. catch (e:IOException) {}
  207. return input.nval.toInt()
  208. }
  209.  
  210. fun Run() {
  211. var PC = 0
  212. var SP = MEMSIZE
  213. var Cmd:Int
  214. var Buf:Int
  215. loop@ while (true) {
  216. Cmd = M[PC++]
  217. if (Cmd >= 0)
  218. M[--SP] = Cmd
  219. else {
  220. when (Cmd) {
  221. cmAdd -> {
  222. SP++
  223. M[SP] += M[SP - 1]
  224. }
  225. cmSub -> {
  226. SP++
  227. M[SP] -= M[SP - 1]
  228. }
  229. cmMult -> {
  230. SP++
  231. M[SP] *= M[SP - 1]
  232. }
  233. cmDiv -> {
  234. SP++
  235. M[SP] /= M[SP - 1]
  236. }
  237. cmMod -> {
  238. SP++
  239. M[SP] %= M[SP - 1]
  240. }
  241. cmNeg -> M[SP] = -M[SP]
  242. cmLoad -> M[SP] = M[M[SP]]
  243. cmSave -> {
  244. M[M[SP + 1]] = M[SP]
  245. SP += 2
  246. }
  247. cmDup -> {
  248. SP--
  249. M[SP] = M[SP + 1]
  250. }
  251. cmDrop -> SP++
  252. cmSwap -> {
  253. Buf = M[SP]
  254. M[SP] = M[SP + 1]
  255. M[SP + 1] = Buf
  256. }
  257. cmOver -> {
  258. SP--
  259. M[SP] = M[SP + 2]
  260. }
  261. cmGOTO -> PC = M[SP++]
  262. cmIfEQ -> {
  263. if (M[SP + 2] == M[SP + 1])
  264. PC = M[SP]
  265. SP += 3
  266. }
  267. cmIfNE -> {
  268. if (M[SP + 2] != M[SP + 1])
  269. PC = M[SP]
  270. SP += 3
  271. }
  272. cmIfLE -> {
  273. if (M[SP + 2] <= M[SP + 1])
  274. PC = M[SP]
  275. SP += 3
  276. }
  277. cmIfLT -> {
  278. if (M[SP + 2] < M[SP + 1])
  279. PC = M[SP]
  280. SP += 3
  281. }
  282. cmIfGE -> {
  283. if (M[SP + 2] >= M[SP + 1])
  284. PC = M[SP]
  285. SP += 3
  286. }
  287. cmIfGT -> {
  288. if (M[SP + 2] > M[SP + 1])
  289. PC = M[SP]
  290. SP += 3
  291. }
  292. cmIn -> {
  293. print('?')
  294. M[--SP] = ReadInt()
  295. }
  296. cmOut -> {
  297. val w = (M[SP] - (M[SP + 1]).toString().length)
  298. for (i in 1..w)
  299. print(" ")
  300. print(M[SP + 1])
  301. SP += 2
  302. }
  303. cmOutLn -> println()
  304. cmStop -> break@loop
  305. else -> {
  306. println("Недопустимый код операции")
  307. break@loop
  308. }
  309. }
  310. }
  311. }
  312. println()
  313. if (SP < MEMSIZE)
  314. println("Код возврата " + M[SP])
  315. }
  316. }
  317.  
  318.  
  319. // Распознаватель
  320. internal object Pars {
  321. val spABS = 1
  322. val spMAX = 2
  323. val spMIN = 3
  324. val spDEC = 4
  325. val spODD = 5
  326. val spHALT = 6
  327. val spINC = 7
  328. val spInOpen = 8
  329. val spInInt = 9
  330. val spOutInt = 10
  331. val spOutLn = 11
  332.  
  333. fun Check(L:Int, M:String) {
  334. if (Scan.Lex != L)
  335. Error.Expected(M)
  336. else
  337. Scan.NextLex()
  338. }
  339.  
  340. // ["+" | "-"] (Число | Имя)
  341. fun ConstExpr():Int {
  342. var v = 0
  343. var X:Obj
  344. var Op:Int
  345. Op = Scan.lexPlus
  346. if ((Scan.Lex == Scan.lexPlus || Scan.Lex == Scan.lexMinus)) {
  347. Op = Scan.Lex
  348. Scan.NextLex()
  349. }
  350. if (Scan.Lex == Scan.lexNum) {
  351. v = Scan.Num
  352. Scan.NextLex()
  353. }
  354. else if (Scan.Lex == Scan.lexName) {
  355. X = Table.Find(Scan.Name)
  356. if (X.Cat == Table.catGuard)
  357. Error.Message("Нельзя определять константу через себя")
  358. else if (X.Cat != Table.catConst)
  359. Error.Expected("имя константы")
  360. else {
  361. v = X.Val
  362. Scan.NextLex()
  363. }
  364. }
  365. else
  366. Error.Expected("константное выражение")
  367. if (Op == Scan.lexMinus)
  368. return -v
  369. return v
  370. }
  371.  
  372. // Имя "=" КонстВыраж
  373. fun ConstDecl() {
  374. val ConstRef:Obj // Ссылка на имя в таблице
  375. ConstRef = Table.NewName(Scan.Name, Table.catGuard)
  376. Scan.NextLex()
  377. Check(Scan.lexEQ, "\"=\"")
  378. ConstRef.Val = ConstExpr()
  379. ConstRef.Typ = Table.typInt //Констант других типов нет
  380. ConstRef.Cat = Table.catConst
  381. }
  382.  
  383. fun ParseType() {
  384. val TypeRef:Obj
  385. if (Scan.Lex != Scan.lexName)
  386. Error.Expected("имя")
  387. else {
  388. TypeRef = Table.Find(Scan.Name)
  389. if (TypeRef.Cat != Table.catType)
  390. Error.Expected("имя типа")
  391. else if (TypeRef.Typ != Table.typInt)
  392. Error.Expected("целый тип")
  393. Scan.NextLex()
  394. }
  395. }
  396.  
  397. // Имя {"," Имя} ":" Тип
  398. fun VarDecl() {
  399. var NameRef:Obj
  400. if (Scan.Lex != Scan.lexName)
  401. Error.Expected("имя")
  402. else {
  403. NameRef = Table.NewName(Scan.Name, Table.catVar)
  404. NameRef.Typ = Table.typInt
  405. Scan.NextLex()
  406. }
  407. while (Scan.Lex == Scan.lexComma) {
  408. Scan.NextLex()
  409. if (Scan.Lex != Scan.lexName)
  410. Error.Expected("имя")
  411. else {
  412. NameRef = Table.NewName(Scan.Name, Table.catVar)
  413. NameRef.Typ = Table.typInt
  414. Scan.NextLex()
  415. }
  416. }
  417. Check(Scan.lexColon, "\":\"")
  418. ParseType()
  419. }
  420.  
  421. // { CONST {ОбъявлКонст ";"} | VAR {ОбъявлПерем ";"} }
  422. fun DeclSeq() {
  423. while ((Scan.Lex == Scan.lexCONST || Scan.Lex == Scan.lexVAR)) {
  424. if (Scan.Lex == Scan.lexCONST) {
  425. Scan.NextLex()
  426. while (Scan.Lex == Scan.lexName) {
  427. ConstDecl() //Объявление константы
  428. Check(Scan.lexSemi, "\";\"")
  429. }
  430. }
  431. else {
  432. Scan.NextLex() // VAR
  433. while (Scan.Lex == Scan.lexName) {
  434. VarDecl() //Объявление переменных
  435. Check(Scan.lexSemi, "\";\"")
  436. }
  437. }
  438. }
  439. }
  440.  
  441. fun IntExpression() {
  442. if (Expression() != Table.typInt)
  443. Error.Expected("выражение целого типа")
  444. }
  445.  
  446. fun StFunc(F:Int):Int {
  447. when (F) {
  448. spABS -> {
  449. IntExpression()
  450. Gen.Abs()
  451. return Table.typInt
  452. }
  453. spMAX -> {
  454. ParseType()
  455. Gen.Cmd(Integer.MAX_VALUE)
  456. return Table.typInt
  457. }
  458. spMIN -> {
  459. ParseType()
  460. Gen.Min()
  461. return Table.typInt
  462. }
  463. spODD -> {
  464. IntExpression()
  465. Gen.Odd()
  466. return Table.typBool
  467. }
  468. }
  469. return Table.typNone // Чтоб не было предупреждений
  470. }
  471.  
  472. fun Factor():Int {
  473. var X:Obj
  474. var T = 0 // Чтоб не было предупреждений
  475. if (Scan.Lex == Scan.lexName) {
  476. X = Table.Find(Scan.Name)
  477. if (X.Cat == Table.catVar) {
  478. Gen.Addr(X) //Адрес переменной
  479. Gen.Cmd(OVM.cmLoad)
  480. Scan.NextLex()
  481. return X.Typ
  482. }
  483. else if (X.Cat == Table.catConst) {
  484. Gen.Const(X.Val)
  485. Scan.NextLex()
  486. return X.Typ
  487. }
  488. else if ((X.Cat == Table.catStProc && X.Typ != Table.typNone)) {
  489. Scan.NextLex()
  490. Check(Scan.lexLPar, "\"(\"")
  491. T = StFunc(X.Val)
  492. Check(Scan.lexRPar, "\")\"")
  493. }
  494. else
  495. Error.Expected("переменная, константа или процедура-функции")
  496. }
  497. else if (Scan.Lex == Scan.lexNum) {
  498. Gen.Const(Scan.Num)
  499. Scan.NextLex()
  500. return Table.typInt
  501. }
  502. else if (Scan.Lex == Scan.lexLPar) {
  503. Scan.NextLex()
  504. T = Expression()
  505. Check(Scan.lexRPar, "\")\"")
  506. }
  507. else
  508. Error.Expected("имя, число или \"(\"")
  509. return T
  510. }
  511.  
  512. fun Term():Int {
  513. var Op:Int
  514. var T = Factor()
  515. if ((Scan.Lex == Scan.lexMult || Scan.Lex == Scan.lexDIV || Scan.Lex == Scan.lexMOD)) {
  516. if (T != Table.typInt)
  517. Error.Message("Несоответствие операции типу операнда" )
  518. do {
  519. Op = Scan.Lex
  520. Scan.NextLex()
  521. T = Factor()
  522. if (T != Table.typInt)
  523. Error.Expected("выражение целого типа")
  524. when (Op) {
  525. Scan.lexMult -> Gen.Cmd(OVM.cmMult)
  526. Scan.lexDIV -> Gen.Cmd(OVM.cmDiv)
  527. Scan.lexMOD -> Gen.Cmd(OVM.cmMod)
  528. }
  529. } while ((Scan.Lex == Scan.lexMult || Scan.Lex == Scan.lexDIV || Scan.Lex == Scan.lexMOD))
  530. }
  531. return T
  532. }
  533.  
  534. // ["+"|"-"] Слагаемое {ОперСлож Слагаемое}
  535. fun SimpleExpr():Int {
  536. var T:Int
  537. var Op:Int
  538. if ((Scan.Lex == Scan.lexPlus || Scan.Lex == Scan.lexMinus)) {
  539. Op = Scan.Lex
  540. Scan.NextLex()
  541. T = Term()
  542. if (T != Table.typInt)
  543. Error.Expected("выражение целого типа")
  544. if (Op == Scan.lexMinus)
  545. Gen.Cmd(OVM.cmNeg)
  546. }
  547. else
  548. T = Term()
  549. if ((Scan.Lex == Scan.lexPlus || Scan.Lex == Scan.lexMinus)) {
  550. if (T != Table.typInt)
  551. Error.Message("Несоответствие операции типу операнда")
  552. do {
  553. Op = Scan.Lex
  554. Scan.NextLex()
  555. T = Term()
  556. if (T != Table.typInt)
  557. Error.Expected("выражение целого типа")
  558. when (Op) {
  559. Scan.lexPlus -> Gen.Cmd(OVM.cmAdd)
  560. Scan.lexMinus -> Gen.Cmd(OVM.cmSub)
  561. }
  562. } while ((Scan.Lex == Scan.lexPlus || Scan.Lex == Scan.lexMinus))
  563. }
  564. return T
  565. }
  566.  
  567. // ПростоеВыраж [Отношение ПростоеВыраж]
  568. fun Expression():Int {
  569. var Op:Int
  570. var T = SimpleExpr()
  571. if ((Scan.Lex == Scan.lexEQ || Scan.Lex == Scan.lexNE ||
  572. Scan.Lex == Scan.lexGT || Scan.Lex == Scan.lexGE ||
  573. Scan.Lex == Scan.lexLT || Scan.Lex == Scan.lexLE))
  574. {
  575. Op = Scan.Lex
  576. if (T != Table.typInt)
  577. Error.Message("Несоответствие операции типу операнда")
  578. Scan.NextLex()
  579. T = SimpleExpr()
  580. if (T != Table.typInt)
  581. Error.Expected("выражение целого типа")
  582. Gen.Comp(Op) //Генерация условного перехода
  583. T = Table.typBool
  584. } //иначе тип равен типу первого простого выражения
  585. return T
  586. }
  587.  
  588. // Переменная = Имя
  589. fun Variable() {
  590. val X:Obj
  591. if (Scan.Lex != Scan.lexName)
  592. Error.Expected("имя")
  593. else {
  594. X = Table.Find(Scan.Name)
  595. if (X.Cat != Table.catVar)
  596. Error.Expected("имя переменной")
  597. Gen.Addr(X)
  598. Scan.NextLex()
  599. }
  600. }
  601.  
  602. fun StProc(P:Int) {
  603. when (P) {
  604. spDEC -> {
  605. Variable()
  606. Gen.Cmd(OVM.cmDup)
  607. Gen.Cmd(OVM.cmLoad)
  608. if (Scan.Lex == Scan.lexComma) {
  609. Scan.NextLex()
  610. IntExpression()
  611. }
  612. else
  613. Gen.Cmd(1)
  614. Gen.Cmd(OVM.cmSub)
  615. Gen.Cmd(OVM.cmSave)
  616. return
  617. }
  618. spINC -> {
  619. Variable()
  620. Gen.Cmd(OVM.cmDup)
  621. Gen.Cmd(OVM.cmLoad)
  622. if (Scan.Lex == Scan.lexComma) {
  623. Scan.NextLex()
  624. IntExpression()
  625. }
  626. else
  627. Gen.Cmd(1)
  628. Gen.Cmd(OVM.cmAdd)
  629. Gen.Cmd(OVM.cmSave)
  630. return
  631. }
  632. spInOpen ->
  633. // Пусто ;
  634. return
  635. spInInt -> {
  636. Variable()
  637. Gen.Cmd(OVM.cmIn)
  638. Gen.Cmd(OVM.cmSave)
  639. return
  640. }
  641. spOutInt -> {
  642. IntExpression()
  643. Check(Scan.lexComma, "\",\"")
  644. IntExpression()
  645. Gen.Cmd(OVM.cmOut)
  646. return
  647. }
  648. spOutLn -> {
  649. Gen.Cmd(OVM.cmOutLn)
  650. return
  651. }
  652. spHALT -> {
  653. Gen.Const(ConstExpr())
  654. Gen.Cmd(OVM.cmStop)
  655. return
  656. }
  657. }
  658. }
  659.  
  660. fun BoolExpression() {
  661. if (Expression() != Table.typBool)
  662. Error.Expected("логическое выражение")
  663. }
  664.  
  665. // Переменная "=" Выраж
  666. fun AssStatement() {
  667. Variable()
  668. if (Scan.Lex == Scan.lexAss) {
  669. Scan.NextLex()
  670. IntExpression()
  671. Gen.Cmd(OVM.cmSave)
  672. }
  673. else
  674. Error.Expected("\":=\"")
  675. }
  676. // Имя ["(" // Выраж | Переменная ")"]
  677. fun CallStatement(sp:Int) {
  678. Check(Scan.lexName, "имя процедуры")
  679. if (Scan.Lex == Scan.lexLPar) {
  680. Scan.NextLex()
  681. StProc(sp)
  682. Check(Scan.lexRPar, "\")\"")
  683. }
  684. else if (sp == spOutLn || sp == spInOpen)
  685. StProc(sp)
  686. else
  687. Error.Expected("\"(\"")
  688. }
  689. fun IfStatement() {
  690. var CondPC:Int
  691. var LastGOTO:Int
  692. Check(Scan.lexIF, "IF")
  693. LastGOTO = 0 //Предыдущего перехода нет
  694. BoolExpression()
  695. CondPC = Gen.PC //Запомн. положение усл. перехода
  696. Check(Scan.lexTHEN, "THEN")
  697. StatSeq()
  698. while (Scan.Lex == Scan.lexELSIF) {
  699. Gen.Cmd(LastGOTO) //Фиктивный адрес, указывающий
  700. Gen.Cmd(OVM.cmGOTO) //на место предыдущего перехода
  701. LastGOTO = Gen.PC //Запомнить место GOTO
  702. Scan.NextLex()
  703. Gen.Fixup(CondPC) //Зафикс. адрес условного перехода
  704. BoolExpression()
  705. CondPC = Gen.PC //Запомн. положение усл. перехода
  706. Check(Scan.lexTHEN, "THEN")
  707. StatSeq()
  708. }
  709. if (Scan.Lex == Scan.lexELSE) {
  710. Gen.Cmd(LastGOTO) //Фиктивный адрес, указывающий
  711. Gen.Cmd(OVM.cmGOTO) //на место предыдущего перехода
  712. LastGOTO = Gen.PC //Запомнить место последнего GOTO
  713. Scan.NextLex()
  714. Gen.Fixup(CondPC) //Зафикс. адрес условного перехода
  715. StatSeq()
  716. }
  717. else
  718. Gen.Fixup(CondPC) //Если ELSE отсутствует
  719. Check(Scan.lexEND, "END")
  720. Gen.Fixup(LastGOTO) //Направить сюда все GOTO
  721. }
  722.  
  723. fun WhileStatement() {
  724. val WhilePC = Gen.PC
  725. Check(Scan.lexWHILE, "WHILE")
  726. BoolExpression()
  727. val CondPC = Gen.PC
  728. Check(Scan.lexDO, "DO")
  729. StatSeq()
  730. Check(Scan.lexEND, "END")
  731. Gen.Cmd(WhilePC)
  732. Gen.Cmd(OVM.cmGOTO)
  733. Gen.Fixup(CondPC)
  734. }
  735.  
  736. fun Statement() {
  737. var X:Obj
  738. if (Scan.Lex == Scan.lexName) {
  739. X = Table.Find(Scan.Name)
  740. if (X.Cat == Table.catModule) {
  741. Scan.NextLex()
  742. Check(Scan.lexDot, "\".\"")
  743. if ((Scan.Lex == Scan.lexName && (X.Name.length + Scan.Name.length <= Scan.NAMELEN)))
  744. X = Table.Find(X.Name + "." + Scan.Name)
  745. else
  746. Error.Expected("имя из модуля " + X.Name)
  747. }
  748. if (X.Cat == Table.catVar)
  749. AssStatement() //Присваивание
  750. else if ((X.Cat == Table.catStProc && X.Typ == Table.typNone))
  751. CallStatement(X.Val) //Вызов процедуры
  752. else
  753. Error.Expected("обозначение переменной или процедуры")
  754. }
  755. else if (Scan.Lex == Scan.lexIF)
  756. IfStatement()
  757. else if (Scan.Lex == Scan.lexWHILE)
  758. WhileStatement()
  759. // иначе пустой оператор
  760. }
  761.  
  762. // Оператор {";" Оператор}
  763. fun StatSeq() {
  764. Statement() //Оператор
  765. while (Scan.Lex == Scan.lexSemi) {
  766. Scan.NextLex()
  767. Statement() //Оператор
  768. }
  769. }
  770.  
  771. fun ImportName() {
  772. if (Scan.Lex == Scan.lexName) {
  773. Table.NewName(Scan.Name, Table.catModule)
  774. if (Scan.Name.compareTo("In") == 0) {
  775. Table.Enter("In.Open", Table.catStProc, Table.typNone, spInOpen)
  776. Table.Enter("In.Int", Table.catStProc, Table.typNone, spInInt)
  777. }
  778. else if (Scan.Name.compareTo("Out") == 0) {
  779. Table.Enter("Out.Int", Table.catStProc, Table.typNone, spOutInt)
  780. Table.Enter("Out.Ln", Table.catStProc, Table.typNone, spOutLn)
  781. }
  782. else
  783. Error.Message("Неизвестный модуль")
  784. Scan.NextLex()
  785. }
  786. else
  787. Error.Expected("имя импортируемого модуля")
  788. }
  789.  
  790. // IMPORT Имя { "," Имя } ";"
  791. fun Import() {
  792. Check(Scan.lexIMPORT, "IMPORT")
  793. ImportName() //Обработка имени импортируемого модуля
  794. while (Scan.Lex == Scan.lexComma) {
  795. Scan.NextLex()
  796. ImportName() //Обработка имени импортируемого модуля
  797. }
  798. Check(Scan.lexSemi, "\";\"")
  799. }
  800.  
  801. // MODULE Имя ";" [Импорт] ПослОбъявл [BEGIN ПослОператоров]
  802. // END Имя "."
  803. fun Module() {
  804. val ModRef:Obj //Ссылка на имя модуля в таблице
  805. Check(Scan.lexMODULE, "MODULE")
  806. if (Scan.Lex != Scan.lexName)
  807. Error.Expected("имя модуля")
  808. //Имя модуля - в таблицу имен
  809. ModRef = Table.NewName(Scan.Name, Table.catModule)
  810. Scan.NextLex()
  811. Check(Scan.lexSemi, "\";\"")
  812. if (Scan.Lex == Scan.lexIMPORT)
  813. Import()
  814. DeclSeq()
  815. if (Scan.Lex == Scan.lexBEGIN) {
  816. Scan.NextLex()
  817. StatSeq()
  818. }
  819. Check(Scan.lexEND, "END")
  820. //Сравнение имени модуля и имени после END
  821. if (Scan.Lex != Scan.lexName)
  822. Error.Expected("имя модуля")
  823. else if (Scan.Name.compareTo(ModRef.Name) != 0)
  824. Error.Expected("имя модуля \"" + ModRef.Name + "\"")
  825. else
  826. Scan.NextLex()
  827. if (Scan.Lex != Scan.lexDot)
  828. Error.Expected("\".\"")
  829. Gen.Cmd(0) // Код возврата
  830. Gen.Cmd(OVM.cmStop) // Команда останова
  831. Gen.AllocateVariables() // Размещение переменных
  832. }
  833.  
  834. fun Compile() {
  835. Table.Init()
  836. Table.OpenScope() //Блок стандартных имен
  837. Table.Enter("ABS", Table.catStProc, Table.typInt, spABS)
  838. Table.Enter("MAX", Table.catStProc, Table.typInt, spMAX)
  839. Table.Enter("MIN", Table.catStProc, Table.typInt, spMIN)
  840. Table.Enter("DEC", Table.catStProc, Table.typNone, spDEC)
  841. Table.Enter("ODD", Table.catStProc, Table.typBool, spODD)
  842. Table.Enter("HALT",Table.catStProc, Table.typNone, spHALT)
  843. Table.Enter("INC", Table.catStProc, Table.typNone, spINC)
  844. Table.Enter("INTEGER", Table.catType, Table.typInt, 0)
  845. Table.OpenScope() //Блок модуля
  846. Module()
  847. Table.CloseScope() //Блок модуля
  848. Table.CloseScope() //Блок стандартных имен
  849. println("\nКомпиляция завершена")
  850. }
  851. }
  852.  
  853. // Лексический анализатор
  854. internal object Scan {
  855. var NAMELEN = 31 // Наибольшая длина имени
  856.  
  857. val lexNone = 0
  858. val lexName = 1
  859. val lexNum = 2
  860. val lexMODULE = 3
  861. val lexIMPORT = 4
  862. val lexBEGIN = 5
  863. val lexEND = 6
  864. val lexCONST = 7
  865. val lexVAR = 8
  866. val lexWHILE = 9
  867. val lexDO = 10
  868. val lexIF = 11
  869. val lexTHEN = 12
  870. val lexELSIF = 13
  871. val lexELSE = 14
  872. val lexMult = 15
  873. val lexDIV = 16
  874. val lexMOD = 17
  875. val lexPlus = 18
  876. val lexMinus = 19
  877. val lexEQ = 20
  878. val lexNE = 21
  879. val lexLT = 22
  880. val lexLE = 23
  881. val lexGT = 24
  882. val lexGE = 25
  883. val lexDot = 26
  884. val lexComma = 27
  885. val lexColon = 28
  886. val lexSemi = 29
  887. val lexAss = 30
  888. val lexLPar = 31
  889. val lexRPar = 32
  890. val lexEOT = 33
  891.  
  892. // Текущая лексема
  893. var Lex:Int = 0
  894.  
  895. // Строковое значение имени
  896. private val Buf = StringBuffer(NAMELEN)
  897. var Name:String = ""
  898. // Значение числовых литералов
  899. var Num:Int = 0
  900.  
  901. private val KWNUM = 34
  902. var nkw = 0
  903. private val KWTable = arrayOfNulls<Item>(KWNUM)
  904.  
  905. private class Item (val Word:String = "", val Lex:Int = 0 )
  906.  
  907. private fun EnterKW(Name:String, Lex:Int) {
  908. KWTable[nkw++] = Item(Name, Lex)
  909. }
  910.  
  911. private fun TestKW():Int {
  912. for (i in nkw - 1 downTo 0) {
  913. if (KWTable[i]!!.Word == Name) {
  914. return KWTable[i]!!.Lex
  915. }
  916. }
  917. return lexName
  918. }
  919.  
  920. private fun Ident() {
  921. var i = 0
  922. Buf.setLength(0)
  923. do {
  924. if (i++ < NAMELEN)
  925. Buf.append(Text.Ch.toChar())
  926. else
  927. Error.Message("Слишком длинное имя")
  928. Text.NextCh()
  929. } while (Character.isLetterOrDigit(Text.Ch.toChar()))
  930. Name = Buf.toString()
  931. Lex = TestKW() // Проверка на ключевое слово
  932. }
  933.  
  934. private fun Number() {
  935. Lex = lexNum
  936. Num = 0
  937. do {
  938. val d = Text.Ch.toInt() - '0'.toInt()
  939. if ((Integer.MAX_VALUE - d) / 10 >= Num)
  940. Num = 10 * Num + d
  941. else
  942. Error.Message("Слишком большое число")
  943. Text.NextCh()
  944. } while (Character.isDigit(Text.Ch.toChar()))
  945. }
  946.  
  947. private fun Comment() {
  948. Text.NextCh()
  949. do {
  950. while (Text.Ch != '*' && Text.Ch != Text.chEOT)
  951. if (Text.Ch == '(') {
  952. Text.NextCh()
  953. if (Text.Ch == '*')
  954. Comment()
  955. }
  956. else
  957. Text.NextCh()
  958. if (Text.Ch == '*')
  959. Text.NextCh()
  960. } while (Text.Ch != ')' && Text.Ch != Text.chEOT)
  961. if (Text.Ch == ')')
  962. Text.NextCh()
  963. else {
  964. Location.LexPos = Location.Pos
  965. Error.Message("Не закончен комментарий")
  966. }
  967. }
  968.  
  969. fun NextLex() {
  970. while ((Text.Ch == Text.chSPACE || Text.Ch == Text.chTAB || Text.Ch == Text.chEOL))
  971. Text.NextCh()
  972. Location.LexPos = Location.Pos
  973. if (Character.isLetter(Text.Ch))
  974. Ident()
  975. else if (Character.isDigit(Text.Ch))
  976. Number()
  977. else
  978. when (Text.Ch) {
  979. ';' -> {
  980. Text.NextCh()
  981. Lex = lexSemi
  982. }
  983. ':' -> {
  984. Text.NextCh()
  985. if (Text.Ch == '=') {
  986. Text.NextCh()
  987. Lex = lexAss
  988. }
  989. else
  990. Lex = lexColon
  991. }
  992. '.' -> {
  993. Text.NextCh()
  994. Lex = lexDot
  995. }
  996. ',' -> {
  997. Text.NextCh()
  998. Lex = lexComma
  999. }
  1000. '=' -> {
  1001. Text.NextCh()
  1002. Lex = lexEQ
  1003. }
  1004. '#' -> {
  1005. Text.NextCh()
  1006. Lex = lexNE
  1007. }
  1008. '<' -> {
  1009. Text.NextCh()
  1010. if (Text.Ch == '=') {
  1011. Text.NextCh()
  1012. Lex = lexLE
  1013. }
  1014. else
  1015. Lex = lexLT
  1016. }
  1017. '>' -> {
  1018. Text.NextCh()
  1019. if (Text.Ch == '=') {
  1020. Text.NextCh()
  1021. Lex = lexGE
  1022. }
  1023. else
  1024. Lex = lexGT
  1025. }
  1026. '(' -> {
  1027. Text.NextCh()
  1028. if (Text.Ch == '*') {
  1029. Comment()
  1030. NextLex()
  1031. }
  1032. else
  1033. Lex = lexLPar
  1034. }
  1035. ')' -> {
  1036. Text.NextCh()
  1037. Lex = lexRPar
  1038. }
  1039. '+' -> {
  1040. Text.NextCh()
  1041. Lex = lexPlus
  1042. }
  1043. '-' -> {
  1044. Text.NextCh()
  1045. Lex = lexMinus
  1046. }
  1047. '*' -> {
  1048. Text.NextCh()
  1049. Lex = lexMult
  1050. }
  1051. Text.chEOT -> Lex = lexEOT
  1052. else ->
  1053. Error.Message("Недопустимый символ")
  1054. }
  1055. }
  1056.  
  1057. fun Init() {
  1058. EnterKW("ARRAY", lexNone)
  1059. EnterKW("BY", lexNone)
  1060. EnterKW("BEGIN", lexBEGIN)
  1061. EnterKW("CASE", lexNone)
  1062. EnterKW("CONST", lexCONST)
  1063. EnterKW("DIV", lexDIV)
  1064. EnterKW("DO", lexDO)
  1065. EnterKW("ELSE", lexELSE)
  1066. EnterKW("ELSIF", lexELSIF)
  1067. EnterKW("END", lexEND)
  1068. EnterKW("EXIT", lexNone)
  1069. EnterKW("FOR", lexNone)
  1070. EnterKW("IF", lexIF)
  1071. EnterKW("IMPORT", lexIMPORT)
  1072. EnterKW("IN", lexNone)
  1073. EnterKW("IS", lexNone)
  1074. EnterKW("LOOP", lexNone)
  1075. EnterKW("MOD", lexMOD)
  1076. EnterKW("MODULE", lexMODULE)
  1077. EnterKW("NIL", lexNone)
  1078. EnterKW("OF", lexNone)
  1079. EnterKW("OR", lexNone)
  1080. EnterKW("POINTER", lexNone)
  1081. EnterKW("PROCEDURE", lexNone)
  1082. EnterKW("RECORD", lexNone)
  1083. EnterKW("REPEAT", lexNone)
  1084. EnterKW("RETURN", lexNone)
  1085. EnterKW("THEN", lexTHEN)
  1086. EnterKW("TO", lexNone)
  1087. EnterKW("TYPE", lexNone)
  1088. EnterKW("UNTIL", lexNone)
  1089. EnterKW("VAR", lexVAR)
  1090. EnterKW("WHILE", lexWHILE)
  1091. EnterKW("WITH", lexNone)
  1092. NextLex()
  1093. }
  1094. }
  1095.  
  1096. // Элемент таблицы имен
  1097. internal class Obj { // Тип записи таблицы имен
  1098. var Name:String = ""// Ключ поиска
  1099. var Cat:Int = 0 // Категория имени
  1100. var Typ:Int = 0 // Тип
  1101. var Val:Int = 0 // Значение
  1102. var Prev:Obj? = null // Указатель на пред. имя
  1103. }
  1104.  
  1105. // Таблица имен
  1106. internal object Table {
  1107. // Категории имён
  1108. val catConst = 1
  1109. val catVar = 2
  1110. val catType = 3
  1111. val catStProc = 4
  1112. val catModule = 5
  1113. val catGuard = 6
  1114. // Типы
  1115. val typNone = 0
  1116. val typInt = 1
  1117. val typBool = 2
  1118. private var Top:Obj? = null//Указатель на вершину списка
  1119. private var Bottom:Obj? = null//Указатель на конец списка
  1120. private var CurrObj:Obj? = null
  1121. // Инициализация таблицы
  1122.  
  1123. fun Init() {
  1124. Top = null
  1125. }
  1126. // Добавление элемента
  1127.  
  1128. fun Enter(N:String, C:Int, T:Int, V:Int) {
  1129. var P = Obj()
  1130. P.Name = N
  1131. P.Cat = C
  1132. P.Typ = T
  1133. P.Val = V
  1134. P.Prev = Top
  1135. Top = P
  1136. }
  1137.  
  1138. fun OpenScope() {
  1139. Enter("", catGuard, typNone, 0)
  1140. if (Top!!.Prev == null)
  1141. Bottom = Top
  1142. }
  1143.  
  1144. fun CloseScope() {
  1145. while (Top!!.Cat != catGuard) {
  1146. Top = Top!!.Prev
  1147. }
  1148. Top = Top!!.Prev
  1149. }
  1150.  
  1151. fun NewName(Name:String, Cat:Int):Obj {
  1152. var obj = Top
  1153. while ((obj!!.Cat != catGuard && obj.Name.compareTo(Name) != 0))
  1154. obj = obj.Prev
  1155. if (obj.Cat == catGuard) {
  1156. obj = Obj()
  1157. obj.Name = Name
  1158. obj.Cat = Cat
  1159. obj.Val = 0
  1160. obj.Prev = Top
  1161. Top = obj
  1162. }
  1163. else
  1164. Error.Message("Повторное объявление имени")
  1165. return obj
  1166. }
  1167.  
  1168. fun Find(Name:String):Obj {
  1169. var obj:Obj?
  1170. Bottom!!.Name = Name
  1171. obj = Top
  1172. while (obj!!.Name != Name) {
  1173. obj = obj.Prev
  1174. }
  1175. if (obj === Bottom)
  1176. Error.Message("Необъявленное имя")
  1177. return obj
  1178. }
  1179.  
  1180. fun FirstVar():Obj? {
  1181. CurrObj = Top
  1182. return NextVar()
  1183. }
  1184.  
  1185. fun NextVar():Obj? {
  1186. var VRef:Obj?
  1187. while (CurrObj !== Bottom && CurrObj!!.Cat != catVar)
  1188. CurrObj = CurrObj!!.Prev
  1189. if (CurrObj === Bottom)
  1190. return null
  1191. else {
  1192. VRef = CurrObj
  1193. CurrObj = CurrObj!!.Prev
  1194. return VRef
  1195. }
  1196. }
  1197. }
  1198.  
  1199. // Драйвер исходного текста
  1200.  
  1201. internal object Text {
  1202. val TABSIZE = 3
  1203. val chSPACE = ' ' // Пробел
  1204. val chTAB = '\t' // Табуляция
  1205. val chEOL = '\n' // Конец строки
  1206. val chEOT = '\u0000' // Конец текста
  1207. var Ok = false
  1208. var Message = "Файл не открыт"
  1209. var Ch = chEOT
  1210. private var f: InputStream = System.`in`
  1211.  
  1212. fun NextCh() {
  1213. try {
  1214. var b = f.read()
  1215. Ch = b.toChar()
  1216. if (b == -1)
  1217. Ch = chEOT
  1218. else if (Ch == '\n') {
  1219. println()
  1220. Location.Line++
  1221. Location.Pos = 0
  1222. Ch = chEOL
  1223. }
  1224. else if (Ch == '\r')
  1225. NextCh()
  1226. else if (Ch != '\t') {
  1227. System.out.write(Ch.toInt())
  1228. Location.Pos++
  1229. }
  1230. else
  1231. do
  1232. print(' ')
  1233. while (++Location.Pos % TABSIZE != 0)
  1234. }
  1235. catch (e:IOException) {}
  1236. }
  1237.  
  1238. fun Reset() {
  1239. f = System.`in`
  1240. Ok = true
  1241. Message = "Ok"
  1242. Location.Pos = 0
  1243. Location.Line = 1
  1244. NextCh()
  1245. }
  1246.  
  1247. fun Close() {
  1248. try {
  1249. f.close()
  1250. }
  1251. catch (e:IOException) {}
  1252. }
  1253.  
  1254. }
Success #stdin #stdout 0.1s 2181120KB
stdin
MODULE Primes;
(* Простые числа от 2 до n *)

IMPORT In, Out;

VAR
   n, c, i, d : INTEGER;

BEGIN
   In.Open;
   In.Int(n);
   Out.Int(n, 0);
   Out.Ln;
   c := 0; (* Счетчик простых *)
   i := 2;
   WHILE i <= n DO
      (* Делим на 2, ... пока не разделится *)
         d := 2;
         WHILE i MOD d # 0 DO 
            INC(d) 
         END;
      IF d = i THEN (* i - простое *)
         INC(c);
         Out.Int(d, 8); 
         IF c MOD 8 = 0 THEN
            Out.Ln;
         END;
      END;
      INC(i);
   END;
   Out.Ln;
   Out.Int(c,0);

END Primes. 
1000
stdout
Компилятор языка О
MODULE Primes;
(* Простые числа от 2 до n *)

IMPORT In, Out;

VAR
   n, c, i, d : INTEGER;

BEGIN
   In.Open;
   In.Int(n);
   Out.Int(n, 0);
   Out.Ln;
   c := 0; (* Счетчик простых *)
   i := 2;
   WHILE i <= n DO
      (* Делим на 2, ... пока не разделится *)
         d := 2;
         WHILE i MOD d # 0 DO 
            INC(d) 
         END;
      IF d = i THEN (* i - простое *)
         INC(c);
         Out.Int(d, 8); 
         IF c MOD 8 = 0 THEN
            Out.Ln;
         END;
      END;
      INC(i);
   END;
   Out.Ln;
   Out.Int(c,0);

END Primes. 
Компиляция завершена
?1000
       2       3       5       7      11      13      17      19
      23      29      31      37      41      43      47      53
      59      61      67      71      73      79      83      89
      97     101     103     107     109     113     127     131
     137     139     149     151     157     163     167     173
     179     181     191     193     197     199     211     223
     227     229     233     239     241     251     257     263
     269     271     277     281     283     293     307     311
     313     317     331     337     347     349     353     359
     367     373     379     383     389     397     401     409
     419     421     431     433     439     443     449     457
     461     463     467     479     487     491     499     503
     509     521     523     541     547     557     563     569
     571     577     587     593     599     601     607     613
     617     619     631     641     643     647     653     659
     661     673     677     683     691     701     709     719
     727     733     739     743     751     757     761     769
     773     787     797     809     811     821     823     827
     829     839     853     857     859     863     877     881
     883     887     907     911     919     929     937     941
     947     953     967     971     977     983     991     997

168
Код возврата 0