|
|
@@ -3,22 +3,113 @@ package module
|
|
|
|
|
|
import (
|
|
|
мФорм "fmt"
|
|
|
- мИсхРуна "p78git.ddns.net/svi/odeft/internal/module/src_rune"
|
|
|
+ мЛог "log"
|
|
|
+ мОс "os"
|
|
|
+ мСтр "strings"
|
|
|
+
|
|
|
+ мЛит "p78git.ddns.net/svi/odeft/internal/module/litera"
|
|
|
+ мАлиас "p78git.ddns.net/svi/odeft/pkg/alias"
|
|
|
+ мКонст "p78git.ddns.net/svi/odeft/pkg/cons"
|
|
|
)
|
|
|
|
|
|
// Модуль -- тип модуля для компилятора
|
|
|
type Модуль struct {
|
|
|
- имя string
|
|
|
- списРун []мИсхРуна.ИсхРуна
|
|
|
+ имя string
|
|
|
+ имяФайла string
|
|
|
+ списЛит []*мЛит.Литера
|
|
|
+ списЛитКоммент []*мЛит.Литера
|
|
|
}
|
|
|
|
|
|
// НовМодуль -- возвращает новый модуль
|
|
|
-func НовМодуль(имя string) (*Модуль, error) {
|
|
|
+func НовМодуль(имяФайла string) (*Модуль, error) {
|
|
|
+ if имяФайла == "" {
|
|
|
+ return nil, мФорм.Errorf("НовМодуль(): имя файла модуля пустое")
|
|
|
+ }
|
|
|
+ списИмяФайла := мСтр.Split(имяФайла, "/")
|
|
|
+ имя := списИмяФайла[len(списИмяФайла)-1]
|
|
|
if имя == "" {
|
|
|
return nil, мФорм.Errorf("НовМодуль(): имя модуля пустое")
|
|
|
}
|
|
|
+ if !мСтр.HasSuffix(имяФайла, ".ou") {
|
|
|
+ return nil, мФорм.Errorf("НовМодуль(): имя файла модуля(%v) имеет неправильное окончание", имяФайла)
|
|
|
+ }
|
|
|
+ имя = мСтр.TrimSuffix(имя, ".ou")
|
|
|
сам := &Модуль{
|
|
|
- имя: имя,
|
|
|
+ имяФайла: имяФайла,
|
|
|
+ имя: имя,
|
|
|
+ списЛит: []*мЛит.Литера{},
|
|
|
+ списЛитКоммент: []*мЛит.Литера{},
|
|
|
+ }
|
|
|
+ if ош := сам.файлПрочитать(); ош != nil {
|
|
|
+ return nil, мФорм.Errorf("НовМодуль(): при чтении файла, ош=\n\t%w", ош)
|
|
|
+ }
|
|
|
+ if ош := сам.найтиНачало(); ош != nil {
|
|
|
+ return nil, мФорм.Errorf("НовМодуль(): при поиске начала модуля ('%v'), ош=\n\t%w", сам.имя, ош)
|
|
|
}
|
|
|
return сам, nil
|
|
|
}
|
|
|
+
|
|
|
+// Ищет в литерах начало модуля
|
|
|
+func (сам *Модуль) найтиНачало() error {
|
|
|
+ { // Поиск начала имени модуля
|
|
|
+ адр := -1
|
|
|
+ словоКонтр := []rune("модуль ")
|
|
|
+ еслиНайдено := false
|
|
|
+ for {
|
|
|
+ if len(сам.списЛит) == 0 {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ адр++
|
|
|
+ литера := сам.списЛит[0]
|
|
|
+ сам.списЛит = сам.списЛит[1:]
|
|
|
+ if литера.Тип() != мКонст.Буква {
|
|
|
+ сам.списЛитКоммент = append(сам.списЛитКоммент, литера)
|
|
|
+ сам.списЛит = сам.списЛит[1:]
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if литера.Знач() == мАлиас.Литера(словоКонтр[0]) {
|
|
|
+ словоКонтр = словоКонтр[1:]
|
|
|
+ if len(словоКонтр) == 0 {
|
|
|
+ мЛог.Printf("Модуль.найтиНачало(): начало модуля найдено")
|
|
|
+ еслиНайдено = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ словоКонтр = []rune("модуль ")
|
|
|
+ }
|
|
|
+ if !еслиНайдено {
|
|
|
+ return мФорм.Errorf("Модуль.найтиНачало(): не найдено начало модуля")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ { // Теперь определить наличие разделителя
|
|
|
+ имяПоиск := мАлиас.Литера("")
|
|
|
+ for {
|
|
|
+ литера := сам.списЛит[0]
|
|
|
+ if литера.Тип() != мКонст.Буква {
|
|
|
+ return мФорм.Errorf("Модуль.найтиНачало(): за ключевым словом 'модуль' нет имени модуля")
|
|
|
+ }
|
|
|
+ имяПоиск += литера.Знач()
|
|
|
+ сам.списЛит = сам.списЛит[1:]
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Читает текст исходного файла
|
|
|
+func (сам *Модуль) файлПрочитать() error {
|
|
|
+ бинДанные, ош := мОс.ReadFile(сам.имяФайла)
|
|
|
+ if ош != nil {
|
|
|
+ return мФорм.Errorf("Модуль.файлПрочитать(): при чтении файла(`%v`), ош=\n\t%w", сам.имяФайла, ош)
|
|
|
+ }
|
|
|
+ стрДанные := string(бинДанные)
|
|
|
+ for _, _руна := range стрДанные {
|
|
|
+ руна, ош := мЛит.НовЛитера(мАлиас.Литера(_руна))
|
|
|
+ if ош != nil {
|
|
|
+ return мФорм.Errorf("Модуль.файлПрочитать(): при создании руны(`%v`), ош=\n\t%w", string(_руна), ош)
|
|
|
+ }
|
|
|
+ сам.списЛит = append(сам.списЛит, руна)
|
|
|
+ }
|
|
|
+ мЛог.Printf("Модуль.файлПрочитать(): всего рун в модуле '%v' = %v\n", сам.имя, len(сам.списЛит))
|
|
|
+ return nil
|
|
|
+}
|