module.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // package module -- тип модуля для компилятора
  2. package module
  3. import (
  4. мФорм "fmt"
  5. мЛог "log"
  6. мОс "os"
  7. мСтр "strings"
  8. мЛит "p78git.ddns.net/svi/odeft/internal/module/litera"
  9. мАлиас "p78git.ddns.net/svi/odeft/pkg/alias"
  10. мКонст "p78git.ddns.net/svi/odeft/pkg/cons"
  11. )
  12. // Модуль -- тип модуля для компилятора
  13. type Модуль struct {
  14. имя string
  15. имяФайла string
  16. списЛит []*мЛит.Литера
  17. списЛитКоммент []*мЛит.Литера
  18. }
  19. // НовМодуль -- возвращает новый модуль
  20. func НовМодуль(имяФайла string) (*Модуль, error) {
  21. if имяФайла == "" {
  22. return nil, мФорм.Errorf("НовМодуль(): имя файла модуля пустое")
  23. }
  24. списИмяФайла := мСтр.Split(имяФайла, "/")
  25. имя := списИмяФайла[len(списИмяФайла)-1]
  26. if имя == "" {
  27. return nil, мФорм.Errorf("НовМодуль(): имя модуля пустое")
  28. }
  29. if !мСтр.HasSuffix(имяФайла, ".ou") {
  30. return nil, мФорм.Errorf("НовМодуль(): имя файла модуля(%v) имеет неправильное окончание", имяФайла)
  31. }
  32. имя = мСтр.TrimSuffix(имя, ".ou")
  33. сам := &Модуль{
  34. имяФайла: имяФайла,
  35. имя: имя,
  36. списЛит: []*мЛит.Литера{},
  37. списЛитКоммент: []*мЛит.Литера{},
  38. }
  39. if ош := сам.файлПрочитать(); ош != nil {
  40. return nil, мФорм.Errorf("НовМодуль(): при чтении файла, ош=\n\t%w", ош)
  41. }
  42. if ош := сам.найтиНачало(); ош != nil {
  43. return nil, мФорм.Errorf("НовМодуль(): при поиске начала модуля ('%v'), ош=\n\t%w", сам.имя, ош)
  44. }
  45. return сам, nil
  46. }
  47. // Ищет в литерах начало модуля
  48. func (сам *Модуль) найтиНачало() error {
  49. { // Поиск начала имени модуля
  50. адр := -1
  51. словоКонтр := []rune("модуль ")
  52. еслиНайдено := false
  53. for {
  54. if len(сам.списЛит) == 0 {
  55. break
  56. }
  57. адр++
  58. литера := сам.списЛит[0]
  59. сам.списЛит = сам.списЛит[1:]
  60. if литера.Тип() != мКонст.Буква {
  61. сам.списЛитКоммент = append(сам.списЛитКоммент, литера)
  62. сам.списЛит = сам.списЛит[1:]
  63. continue
  64. }
  65. if литера.Знач() == мАлиас.Литера(словоКонтр[0]) {
  66. словоКонтр = словоКонтр[1:]
  67. if len(словоКонтр) == 0 {
  68. мЛог.Printf("Модуль.найтиНачало(): начало модуля найдено")
  69. еслиНайдено = true
  70. break
  71. }
  72. continue
  73. }
  74. словоКонтр = []rune("модуль ")
  75. }
  76. if !еслиНайдено {
  77. return мФорм.Errorf("Модуль.найтиНачало(): не найдено начало модуля")
  78. }
  79. }
  80. { // Теперь определить наличие разделителя
  81. имяПоиск := мАлиас.Литера("")
  82. for {
  83. литера := сам.списЛит[0]
  84. if литера.Тип() != мКонст.Буква {
  85. return мФорм.Errorf("Модуль.найтиНачало(): за ключевым словом 'модуль' нет имени модуля")
  86. }
  87. имяПоиск += литера.Знач()
  88. сам.списЛит = сам.списЛит[1:]
  89. }
  90. }
  91. }
  92. // Читает текст исходного файла
  93. func (сам *Модуль) файлПрочитать() error {
  94. бинДанные, ош := мОс.ReadFile(сам.имяФайла)
  95. if ош != nil {
  96. return мФорм.Errorf("Модуль.файлПрочитать(): при чтении файла(`%v`), ош=\n\t%w", сам.имяФайла, ош)
  97. }
  98. стрДанные := string(бинДанные)
  99. for _, _руна := range стрДанные {
  100. руна, ош := мЛит.НовЛитера(мАлиас.Литера(_руна))
  101. if ош != nil {
  102. return мФорм.Errorf("Модуль.файлПрочитать(): при создании руны(`%v`), ош=\n\t%w", string(_руна), ош)
  103. }
  104. сам.списЛит = append(сам.списЛит, руна)
  105. }
  106. мЛог.Printf("Модуль.файлПрочитать(): всего рун в модуле '%v' = %v\n", сам.имя, len(сам.списЛит))
  107. return nil
  108. }