aboutsummaryrefslogtreecommitdiff
path: root/model
diff options
context:
space:
mode:
author2026-03-09 23:05:42 +0300
committer2026-03-09 23:05:42 +0300
commit00394a80501960ad26787b5c44435ed5ed67ad84 (patch)
tree672eb918c552c858f32e9533dc3799af6b75769f /model
parent'-' sign in words accepted (diff)
downloadconf-0.1.0.tar.gz
conf-0.1.0.tar.bz2
conf-0.1.0.tar.xz
conf-0.1.0.zip
Полностью переписал библиотеку. Перевёл с EBNF на PEG.v0.1.0
Diffstat (limited to 'model')
-rw-r--r--model/body.go28
-rw-r--r--model/directive.go9
-rw-r--r--model/lookup.go56
-rw-r--r--model/model.go44
-rw-r--r--model/setting.go6
-rw-r--r--model/value.go85
-rw-r--r--model/visitor.go6
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
-}