Dsl syntax
caution
This doc is written manually. The implementation may differ. If it does, then either this doc is wrong or the implementation is wrong. In any case, them disagreeing is a bug. Please file an issue!
warning
While something may be valid to be parsed, it may not be valid as a construct and may generate an error deeper down.
Top-level item is Device.
- '*' is used to signal 0 or more instances.
- '?' is used to signal 0 or 1 instances.
- '|' is used as an 'or'. One of the options in the chain can be used.
- '( )' is used to group things together.
- Any
keyword
or brackets in the grammer use backticks just like word 'keyword' on this line.
This doesn't map perfectly on the YAML and JSON inputs, but they should be made as close as possible.
Device:
GlobalConfigList
ObjectList
GlobalConfigList:
(
config
{
GlobalConfig*}
)?
GlobalConfig:
(
type
DefaultRegisterAccess
=
Access;
)
| (type
DefaultFieldAccess
=
Access;
)
| (type
DefaultBufferAccess
=
Access;
)
| (type
DefaultByteOrder
=
ByteOrder;
)
| (type
DefaultBitOrder
=
BitOrder;
)
| (type
RegisterAddressType
=
IntegerType;
)
| (type
CommandAddressType
=
IntegerType;
)
| (type
BufferAddressType
=
IntegerType;
)
| (type
NameWordBoundaries
=
NameWordBoundaries;
)
| (type
DefmtFeature
=
String;
)
NameWordBoundaries: This specifies the input, not the output. Only applies to object and field names.
[Boundary*]
| String
ObjectList:
(Object(
,
Object)*,
?)?
Object:
Block
| Register
| Command
| Buffer
| RefObject
RefObject: An object that is a copy of another object. Any items in the object are overrides.
AttributeList
ref
IDENTIFIER=
Object
AttributeList:
Attribute*
Attribute: Used for documentation and conditional compilation
(
#
[
doc
=
STRING]
)
| (#
[
cfg
(
ConfigurationPredicate)
]
)
Block:
AttributeList
block
IDENTIFIER{
BlockItemList ObjectList}
BlockItemList:
BlockItem*
BlockItem:
(
const
ADDRESS_OFFSET
=
INTEGER;
)
| (const
Repeat)
Register:
AttributeList
register
IDENTIFIER{
RegisterItemList FieldList}
RegisterItemList:
RegisterItem*
RegisterItem:
(
type
Access
=
Access;
)
| (type
ByteOrder
=
ByteOrder;
)
| (type
BitOrder
=
BitOrder;
)
| (const
ADDRESS
=
INTEGER;
)
| (const
SIZE_BITS
=
INTEGER;
)
| (const
RESET_VALUE
=
INTEGER | U8_ARRAY;
)
| (const
Repeat)
| (const
ALLOW_BIT_OVERLAP
= BOOL;
)
| (const
ALLOW_ADDRESS_OVERLAP
= BOOL;
)
Access:
(
ReadWrite
|RW
)
| (ReadOnly
|RO
)
| (WriteOnly
|WO
)
ByteOrder:
LE
|BE
BitOrder:
LSB0
|MSB0
FieldList:
(Field (
,
Field)*,
?)
Field:
AttributeList
IDENTIFIER:
Access? BaseType FieldConversion?=
FieldAddress
FieldConversion:
(
as
try
? TYPE_PATH)
| (as
try
?enum
IDENTIFIER{
EnumVariantList}
)
EnumVariantList:
EnumVariant(
,
EnumVariant)*,
?
EnumVariant:
AttributeList
IDENTIFIER (=
EnumValue)?
EnumValue:
INTEGER|
default
|catch_all
FieldAddress:
INTEGER
| (INTEGER..
INTEGER)
| (INTEGER..=
INTEGER)
BaseType:
bool
|uint
|int
Command:
AttributeList
command
IDENTIFIER CommandValue?
CommandValue:
(
=
INTEGER)
| ({
CommandItemList (in
{
FieldList}
,
?)? (out
{
FieldList}
,
?)?}
)
CommandItemList:
CommandItem*
CommandItem: Commands have data going in and out, so they need two separate data field types. If no in fields, then no data is sent. If no out fields, then no data is returned.
(
type
ByteOrder
=
ByteOrder;
)
| (type
BitOrder
=
BitOrder;
)
| (const
ADDRESS
=
INTEGER;
)
| (const
SIZE_BITS_IN
=
INTEGER;
)
| (const
SIZE_BITS_OUT
=
INTEGER;
)
| (const
Repeat)
| (const
ALLOW_BIT_OVERLAP
= BOOL;
)
| (const
ALLOW_ADDRESS_OVERLAP
= BOOL;
)
Repeat:
REPEAT
=
{
count
:
INTEGER,
stride
:
INTEGER,
?}
;
Buffer:
AttributeList
buffer
IDENTIFIER(:
Access)? (=
INTEGER)?