---
# System prepended metadata

title: Описание типа данных

---

# Описание типа данных

## Пример

```
data MyType<data Magic, const WithContent> {
    magic: Magic,
    if 'eq(WithContent, 1) {
        length: bytes<8, little> at magic.part@end shift 0,
        body: bytes<length, little>,
    },
}
```

## Грамматика в EBNF

```ebnf
Data = "data" ID "<" Comma<DataParam> ">" "{" Comma<DataStmt> "}" |
       "data" ID "{" Comma<DataStmt> "}";

DataParam = "const" ID |
            "data" ID |
            "endianness" ID ;

DataStmt = ID ":" ID [ AtModifier ] [ ShiftModifier ] |
           ID ":" ID "<" DataExpr ">" [ AtModifier ] [ ShiftModifier ] |
           "if" SmtExpr "{" Comma<DataStmt> "}" ;

DataExpr = BitVecLiteral |
           BitVecOp "(" Comma<SmtExpr> ")" |
           ID "(" Comma<SmtExpr> ")" |
           ID |
           ID "<" Comma<DataExpr> ">" |
           Endianness;

AtModifier = "at" Dot<ID> "@" LocationAnchor | "at" Dot<ID> ;
ShiftModifier = "shift" SmtExpr ;
LocationAnchor = "start" | "end" ;
Endianness = "little" | "big";
```

## Описание грамматики

### Data

```
Data:
    "data" ID "<" Comma<DataParam> ">" "{" Comma<DataStmt> "}"
    "data" ID "{" Comma<DataStmt> "}"

DataParam = "const" ID
            "data" ID
            "endianness" ID
```

Нетерминал, соответсвующий всему блоку описания типа данных. Первый вариант соответствует параметрическому типу. Второй — непараметрическому.

Нетерминал `DataParam` соответствует описанию одного параметра типа данных. Три его варианта соответствуют параметрам типа константа, тип данных и порядок байт.

Сответствующая AST-нода `data::Data` хранит в себе строку с именем, список параметром `data::Param` и список выражений `data::Statement`, являющийся телом определения данного типа.

AST-нода `data::Param` хранит в себе имя данного параметра.

### DataStmt

```
DataStmt:
    ID ":" ID [ AtModifier ] [ ShiftModifier ]
    ID ":" ID "<" Comma<DataExpr> ">" [ AtModifier ] [ ShiftModifier ]
    "if" SmtExpr "{" Comma<DataStmt> "}"
```

Нетерминал соответствует одному выражению в теле определения типа. Три его варианта представляют из себя определение одного поля типа (`datamodel::Relation`) без параметров или с ними, или условного набора других выражений.

В первых двух случаях нетерминал `ID` соответствует тому типу, на который ссылается данный `Relation`. Во втором случае нетерминал `DataExpr` описывает параметры этого типа.

Имеются так же два опциональных модификатора: `AtModifier` и `ShiftModifier`, отвечающие соответственно за `Relation::Location` и `Relation::offset`.

В третьем случае выражение `SmtExpr` задает условие наличия вложенного выражения. Если вложенное выражение так же представляет из себя условное выражение, условия логически умножаются. В противном случае это условие задает `Relation::condition`.

AST-нода хранит в себе:
* в первых двух вариантах строку имени, строку типа, вектор его параметров `data::Expr` (в первом случае пустой) на который ссылается поле, опциональные модификаторы `data::AtModifier` и `data::ShiftModifier`;
* в третьем варианте условие `SmtExpr` и входящие в его тело выражения `data::Statement`.

### DataExpr

По сути представляет из себя модификацию SmtExpr. Этот нетерминал описывает возможные параметры типа. Он может соответствовать констатным параметрам, а так же другим (возможно параметризированным) типам или параметрам порядка байтов.

```
DataExpr:
    BitVecLiteral
    BitVecOp "(" Comma<SmtExpr> ")"
    ID "(" Comma<SmtExpr> ")"
    ID
    ID "<" Comma<DataExpr> ">"
    Endianness
```

Нетерминал расширяет нетерминал `SmtExpr` двумя последними вариантами. Первый из них соответствует описанию другого типа. Второй — описанию порядка байтов.

### AtModifier

```
AtModifier:
    "at" Dot<ID> "@" LocationAnchor
    "at" Dot<ID>
```

Нетерминал соответствует модификатору, отвечающему за `Location` соответствующего `Relation`. Второй вариант соответствует первому с параметром `LocationAnchor` равном `end` (значение по умолчанию).

Соответствующая AST-нода хранит в себе вектор строк — `LocationOrigin` и enum `LocationAnchor`.


### ShiftModifier

```
ShiftModifier:
    "shift" SmtExpr
```

Нетерминал соответствует модификатору `Relation::offset`. AST-нода хранит в себе одно значение: `SmtExpr`.
