# Описание типа данных ## Пример ``` 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`.