diff options
| author | 2026-03-09 23:05:42 +0300 | |
|---|---|---|
| committer | 2026-03-09 23:05:42 +0300 | |
| commit | 00394a80501960ad26787b5c44435ed5ed67ad84 (patch) | |
| tree | 672eb918c552c858f32e9533dc3799af6b75769f /model | |
| parent | '-' sign in words accepted (diff) | |
| download | conf-00394a80501960ad26787b5c44435ed5ed67ad84.tar.gz conf-00394a80501960ad26787b5c44435ed5ed67ad84.tar.bz2 conf-00394a80501960ad26787b5c44435ed5ed67ad84.tar.xz conf-00394a80501960ad26787b5c44435ed5ed67ad84.zip | |
Полностью переписал библиотеку. Перевёл с EBNF на PEG.v0.1.0
Diffstat (limited to '')
| -rw-r--r-- | model/body.go | 28 | ||||
| -rw-r--r-- | model/directive.go | 9 | ||||
| -rw-r--r-- | model/lookup.go | 56 | ||||
| -rw-r--r-- | model/model.go | 44 | ||||
| -rw-r--r-- | model/setting.go | 6 | ||||
| -rw-r--r-- | model/value.go | 85 | ||||
| -rw-r--r-- | model/visitor.go | 6 |
7 files changed, 44 insertions, 190 deletions
diff --git a/model/body.go b/model/body.go deleted file mode 100644 index b7b4a0c..0000000 --- a/model/body.go +++ /dev/null @@ -1,28 +0,0 @@ -package model - -import ( - "errors" - "fmt" -) - -type Body []any - -var ErrInvalidType = errors.New("invalid type") - -func (d Body) Execute(v Visitor) error { - for _, it := range d { - switch it := it.(type) { - case *Setting: - if err := v.VisitSetting(it.Key, it.Value); err != nil { - return err - } - case *Directive: - if err := v.VisitDirective(it.Name, it.Arguments, it.Body); err != nil { - return err - } - default: - return fmt.Errorf("%w: %t", ErrInvalidType, it) - } - } - return nil -} diff --git a/model/directive.go b/model/directive.go deleted file mode 100644 index 3852e72..0000000 --- a/model/directive.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type Directive struct { - Name string - Arguments Values - Body Body -} - -type Directives []*Directive diff --git a/model/lookup.go b/model/lookup.go deleted file mode 100644 index 880a1f8..0000000 --- a/model/lookup.go +++ /dev/null @@ -1,56 +0,0 @@ -package model - -import ( - "os" - "strings" -) - -// WordLookup тип определяющий функцию поиска замены слов при -// стрингификации Values. -type WordLookup func(word Word) string - -// chainLookup утилитарная функция для последовательных применений функций -// поиска до первого нахождения подстановки. Если returnOrigin == true, -// то в случае неудачи вернёт имя слова. -func chainLookup(lookups ...WordLookup) WordLookup { - return func(word Word) string { - for _, lookup := range lookups { - if v := lookup(word); v != "" { - return v - } - } - return "" - } -} - -// LookupEnv функция типа WordLookup которая пытается подставить вместо word -// соответствующую ему переменную окружения ОС. При этом он срабатывает только -// если слово начинается со знака `$`. -func LookupEnv(word Word) string { - if !strings.HasPrefix(string(word), "$") { - return "" - } - varName := strings.TrimPrefix(string(word), "$") - if result, ok := os.LookupEnv(varName); ok { - return result - } - return "" -} - -// LookupSubst функция типа WordLookup которая пытается подставить вместо word -// значение из словаря подстановок по соответствующему ключу. -func LookupSubst(subst map[Word]string) WordLookup { - return func(word Word) string { - if result, ok := subst[word]; ok { - return result - } - return "" - } -} - -// Origin возвращает просто строковое представления слова. Если поставить в -// конце цепочки - то вместо пустоты (если предыдущие фильтры не сработали) -// вернётся оригинальное имя слова. -func Origin(word Word) string { - return string(word) -} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..2bc6dfb --- /dev/null +++ b/model/model.go @@ -0,0 +1,44 @@ +package model + +import ( + "iter" +) + +type Ident string + +type Command struct { + Name Ident + Args []any + Group Group +} + +// Value returns first argument of command. +func (c *Command) Value() any { + if len(c.Args) > 0 { + return c.Args[0] + } + return nil +} + +type Group []Command + +// Get returns first command with given name. +func (g Group) Get(name Ident) *Command { + for _, c := range g { + if c.Name == name { + return &c + } + } + return nil +} + +// Filter commands by predicate and returns iterator over filtered commands. +func (g Group) Filter(predicate func(c *Command) bool) iter.Seq[*Command] { + return func(yield func(*Command) bool) { + for _, c := range g { + if predicate(&c) && !yield(&c) { + return + } + } + } +} diff --git a/model/setting.go b/model/setting.go deleted file mode 100644 index 363a8a9..0000000 --- a/model/setting.go +++ /dev/null @@ -1,6 +0,0 @@ -package model - -type Setting struct { - Key string - Value Values -} diff --git a/model/value.go b/model/value.go deleted file mode 100644 index 9fa8e9b..0000000 --- a/model/value.go +++ /dev/null @@ -1,85 +0,0 @@ -package model - -import ( - "fmt" - "strconv" - "strings" -) - -type Value any - -type Values []Value - -// BuildString собирает из значений Value цельную строку, при этом приводя все -// значения к типу string. Так же принимает функции типа WordLookup, которые -// последовательно будут пытаться привести значения типа Word к -// контекстозависимым значениям. Например, пытаться находить по имени переменную -// окружения ОС. -func (v Values) BuildString(lookups ...WordLookup) string { - sw := strings.Builder{} - - for _, v := range v { - switch v := v.(type) { - case string: - sw.WriteString(v) - case float64: - sw.WriteString(strconv.FormatFloat(v, 'f', 5, 64)) - case int: - sw.WriteString(strconv.Itoa(v)) - case bool: - if v { - sw.WriteString("true") - continue - } - sw.WriteString("false") - case Word: - sw.WriteString(chainLookup(lookups...)(v)) - } - } - - return sw.String() -} - -func (v Values) String() string { - result := make([]string, 0, len(v)) - - for _, v := range v { - switch v := v.(type) { - case string: - result = append(result, v) - case float64: - result = append(result, strconv.FormatFloat(v, 'f', 5, 64)) - case int: - result = append(result, strconv.Itoa(v)) - case bool: - if v { - result = append(result, "true") - continue - } - result = append(result, "false") - case Word: - result = append(result, string(v)) - } - } - - return strings.Join(result, " ") -} - -func (v Values) Int() (int, error) { - if len(v) != 1 { - return 0, fmt.Errorf("AsInt can return only single value (there is %d values)", len(v)) - } - val := v[0] - switch val := val.(type) { - case int: - return val, nil - case string: - return strconv.Atoi(val) - case float64: - return int(val), nil - default: - return 0, fmt.Errorf("invalid type for convert to int: %t", val) - } -} - -type Word string diff --git a/model/visitor.go b/model/visitor.go deleted file mode 100644 index 3f290d3..0000000 --- a/model/visitor.go +++ /dev/null @@ -1,6 +0,0 @@ -package model - -type Visitor interface { - VisitDirective(ident string, args Values, body Body) error - VisitSetting(key string, values Values) error -} |
