date:20170726
在Storage中状态变量的层级
静态大小的变量(除了mapping和动态大小的数组类型)从位置0开始连续的排列的。如果可以,不足32位的数据将会按照下面的规则打包在一个数据槽中:
- Storage数据槽中的第一项按照低端对齐方式存储。(?The first item in a storage slot is stored lower-order aligned.)
- 基础数据类型只使用它们所需的内存大小来保存数据。
- 如果基础数据类型的大小超过了数据槽中的剩余大小,会把数据保存在下个数据槽中。
- 结构体和数组数据总是以新的数据槽开始,并且占用整个数据槽(但是在结构体的项或者数组将会根据各自的规则紧紧的打包在一起)
**
警告:当使用小鱼32位大小的元素时,合约可能会消耗更多的gas。这是因为EVM每次操作都是32位的。因此,如果数据小于32位,EBM必须进行更多的操作来从32位数据中取出所需的数据。
使用小于32位数据的唯一好处是:由于编译器把多个数据打包到一个数据槽中,你如果要处理数据就可以在一个操作中读写。当处理函数参数或者内存值的时候,就没有这些好处了,因为编译器不会打包这些数据的。
最后,为了允许EVM优化存储,要保证你对storage变量和struct
成员已经排过序了,以方便打包。例如,storage变量的声明顺序uint128,uit128,uint256
会优于uint128,uint256,uint128
,因为前一个声明顺序只会消耗2个storage数据槽,但是后面的声明顺序会消耗3个。
**
结构体和数组的元素都是按照顺序存储的,就好像是他们都是被给定的一样。
由于他们有不可预估的大小,mapping和动态大小数组累心使用Keccak-256 哈希计算来找到他们的起始位置或者数组数据。这些起始位置总是占用整个数据槽。
根据上面的规则(或者递归这个规则,mapping里的mapping或array里的array),mapping或者动态数组本身在storage的某个位置p
占据了一个(不完整的)数据槽。对于动态数组。这个数据槽存储了数组的长度(bytes数组和string是例外,参看下文)。对于mapping,这个数据槽没有使用(但是这是需要的,这样两个相邻且相同的mapping就会有不同的hash分布了)。数组数据位于keccak256(p)
,键k
对应的数据位于keccak256(k. p)
,其中的.
是连接符。如果值是非基础类型数据,数据的位置会加上一个偏移量keccak(k . p)
。
bytes
和string
的数据都保存在同一个数据槽中,如果数据较短,也会保存他们的长度。特殊的:如果数据是31
字节长,它会按照大端顺序存储(左对齐)且最低位保存length * 2
。如果数据更长,主数据槽会保存length*2 + 1
,数据跟平常一样保存在keccak256(slot)
。
所以如下的合约代码:
pragma solidity ^0.4.0;
contract C {
struct s { uint a; uint b; }
uint x;
mapping(uint => mapping(uint => s)) data;
}
数据data[4][9].b
的位置是keccak(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1
。
内存中的层级
solidity中保留了3种256位的数据槽:
- 0 - 64:哈希方法使用的零空间(?scratch space for hashing methods)
- 64 - 96:当前的分配内存的大小(众所周知,空白内存的指针)
零空间可以用于表达式之间(例如,在内联汇编)。
solidity总是把新的对象放置在空白内存指针指向的内存并且内存不会释放(这会在以后的版本中改变)
警告:solidity中的一些操作会需要大于64字节的临时内存,因此会和零空间不匹配。他们会使用空白指针指向的内存空间,但是他们的生命周期很短,指针不会更新。内存可能或者不会重置。由于这个原因,我们不应该假设空白内存是被置零了的。
调用数据的层级
当Solidity合约发布了,并且当它从另一个合约被调用,输入数据会被假定以abi的形式传入。ABI形式需要参数填充为32字节的整数倍。内部函数调用使用不同的约定。
内部 - 清除变量(Internals - Cleaning Up Variables)
当值的长度小于256位时,由于某些原因,剩余位必须要清除。solidity编译器被设计为:在对这些保留位进行操作之前,会清除这些保留位,因为操作可能会生成潜在的垃圾。例如,在把值写进内存之前,保留位需要被清除,因为内存的内容可以被用来存储哈希值或者给消息调用传递数据。类似的,在把值存进storage之前,保留位必须要清除,否则会观察到错误的值。
另一方面,如果对下一个操作没有产生影响,我们也不需要清理这些位。例如,由于非零的值都会被JUMPI
指令看成是true
,这些布尔量在JUMPI
指令的条件执行之前,也没有必要清除。
为了实现上述的原则,Solidity编译器会对从堆栈中载入的输入数据进行清理。
不同的类型有不同的清理规则:
类型 | 有效值 | 非法值处理方法 |
---|---|---|
枚举数为n的枚举类型 | 0到 n-1 | 抛出异常 |
布尔类型 | 0或1 | 1 |
有符号整形 | 符号扩展字 | 目前只是精磨包裹,以后会抛出异常 |
无符号整形 | 高位置零 | 目前只是精磨包裹,以后会抛出异常 |
内部 - 优化器(Internals - The Optimizer)
Solidiy优化器在汇编层面操作,所以可以当做并且也被用于另一种语言。它会把指令序列按照JUMPs和JUMPDESTs分割成代码块。在这些代码块中,指令会被分析并且对栈,对内存或者对storage的每次改动都被记录为表达式,表达式由一系列的指令和参数组成。这些参数本质上又指向其他表达式。主要的理念是找到总是跟输入相同的表达式,并把他们组合成一个表达式集合。优化器首先会尝试在一个已知的表达式列表中找到和新的表达式匹配的表达式。如果列表中不存在,表达式会按照constant + constant = sum_of_constants
或者X * 1 = X
的规则来简化。当对这些递归操作之后,虽然第二个参数是一个更加复杂的表达式,但是我们知道它总是为1,我们就可以使用第二个规则。对内存和storage位置的修改会清除内存和storage的值,因为我们不知道他们的地址是否是不同的:如果我们先对地址x写,然后对地址y写,并且都是输入变量,第二个变量可能会覆盖第一个,所以在我们对y写操作之后,就不知道x的值。另外,如果一个简单的表达式x-y得到一个非零的静态常量,我们可以推出x的值。
在这个操作之后,我们知道哪个表达式必须是在堆栈最后,并且对内存和storage有一系列的修改。这些信息会被一起记录在基础代码块中并且会把它们连接起来。另外,堆栈信息,storage和内存配置,保存在下一个代码块中。如果我们知道所有JUMP和JUMPI指令的跳转目的,我们可以为程序建立完整的控制流图谱。如果只有对一个跳转不知道目的地址(根据规则,这是可能的,跳转地址可以通过输入计算出来),我们必须擦除输入状态块的所有状态信息,因为他可能是不确定跳转的目的地址。如果JUMPI的条件是常亮,就会变成非条件跳转。
最后一步,每个代码块的代码都会被重新生成。在代码块最后会从这些堆栈表达式中生成一个依赖图表。任何不是该图表的一部分的表达式都会被丢弃。现在生成了新的代码,按照他们在原代码中的顺序对堆栈和内存进行修改(会删除无效的更改),最后在堆栈正确的地方生成所需的所有的值。
这些步骤会应用到对每个基础块,并且新生成的代码如果更小,会替换原来的代码块。如果基础块按照JUMPI分割,且在分析过程中,如果条件是常量,JUMPI会被替换为依赖常量,因此如下代码:
var x = 7;
data[7] = 9;
if (data[x] != x + 2)
return 2;
else
return 1;
会被简化,并且编译简化代码:
data[7] = 9;
return 1;
尽管刚开始的时候会包含跳转指令,但是优化后之后就没有了。
源码映射
作为AST输出的一部分,编译器会提供每个AST节点的源码。这可以有多种用途,静态分析工具基于AST报告错误,调试工具用来高亮局部变量和他们的使用。
另外,编译器会生成字节码到通过指令生成的源码的映射。这也对静态分析工具在字节码层面操作很重要,并且调试器可以显示源码的当前位置或者处理断点。
两种源码映射都使用整形标识符来引用源码。这些规整的数组是对被称为sourceList
的源码文件的索引。这些源码文件时combined-json文件和json/npm编译器输出的一部分。
在AST中使用如下标记来对源码进行映射:
s:l:f
其中s
是源码起始位置的偏移,l
是源码长度,以字节为单位,f
是源码索引。
源码映射的字节码编码会更加复杂:是用;
分割的一系列的s:l:f:j
。每个元素对应于一个指令。例如你不能使用字节偏移但是可以使用指令偏移(指令长度不长于一个字节)。字段s
,l
和f
位于上部分,j
,可以是i
,o
或者-
用来指示是否是跳转指令跳转到函数,从函数中返回还是只是循环中的一个常规的跳转。
为了压缩这些代码映射的字节码,会使用下面的规则:
- 如果字段为空,会使用前一个元素的值
- 如果
:
丢失了,下面的字段都会被忽略
这意味着下面的源码映射都表达了相同的信息:
1:2:1;1:9:1;2:1:2;2:1:2;2:1:2
1:2:1;:9;2::2;;
合约元数据
Solidity编译器会自动生成JSON文件,合约元数据,它包含当前合约的信息。它可以用来查询当前源码使用的编译器版本,ABI和NatSpec文档,来更安全的跟合约互动和验证它的源码,
编译器依赖元数据文件的Swarm哈希来结束每个合约的字节码(详情请看下面章节),所以你可以通过文件来授权取回文件,而不需要一个中心化的数据提供方。
当然,你必须把文件发布到Swarm(或者其他服务器),那么其他人就可以访问到了。该文件可以通过命令solc --metadata
来生成,文件名称为ContractName_meta.json
。它会包含源文件的Swarm引用。所以,你必须把所有源文件和元数据文件都上传上去。
元数据文件有下面的格式。例子以可读的形式呈现。格式化的元数据必须正确使用引号,减少空格来压缩数据,所有对象的名字都要排序,以达到唯一的形式。当然注释也是不允许的,这里只是为了说明。
{
// 必须字段:元数据格式的版本
version: "1",
// 必须字段:源码的语言,通常选择一个子版本
language: "Solidity",
// 必须字段:编译器详情信息,内容是语言的详细信息
compiler: {
// Solidity需要这个信息:编译器版本
version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
// 可选:编译器二进制的Hash值
keccak256: "0x123..."
},
// 必须字段:编译源码文件/源单元,文件名称为键
sources:
{
"myFile.sol": {
// 必须字段:源文件的keccak256的Hash值
"keccak256": "0x123...",
// 必须字段(除非”content”字段被使用,参看下文):文件的短URL(s),协议任意,但是推荐使用Swram url。
"urls": [ "bzzr://56ab..." ]
},
"mortal": {
// 必须字段:源码的keccak256 hash值。
"keccak256": "0x234...",
// 必须字段(除非“url“被使用):源文件的字面内容
"content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
}
},
// 必须字段:编译器设置
settings:
{
// 必须字段,solidity需要:排过序的remapping
remappings: [ ":g/dir" ],
// 可选字段:优化设置(默认enable字段为false)
Optional: Optimizer settings (enabled defaults to false)
optimizer: {
enabled: true,
runs: 500
},
// 必须字段,solidity需要:这个元数据文件所对应的合约文件和名称或者库
compilationTarget: {
"myFile.sol": "MyContract"
},
// 必须字段,solidity需要:所需库的地址
libraries: {
"MyLib": "0x123123..."
}
},
// 必须字段:合约的生成信息。
output:
{
// 必须字段:合约的ABI定义
abi: [ ... ],
// 必须字段:该合约的NatSpec 使用文档
userdoc: [ ... ],
// 必须字段:合约的NatSpec开发文档
devdoc: [ ... ],
}
}
注意:注意ABI定义么有固定的顺序。它因编译器版本不同而不同
注意:由于目标合约的字节码有元数据的hash,对元数据文件的任何修改将会导致字节码的改变。另外,元数据文件中也有源文件的hash,任意源文件的任何改变都会导致不同的元数据文件和不同的字节码。
字节码形式的元数据hash编码(Encoding of the Metadata Hash in the Bytecode)
因为我们可能在未来提供取回元数据文件的方法,映射{"bzzr0":<Swarm hash>}
被存储为CBOR-编码(DBOR)。由于编码的起始位置不容易找到,它的长度添加为2个字节,大端存储编码。当前版本的Solidity编译器会在字节码末尾添加下面的内容。
0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
所以为了取回数据,已发布字节码的末尾可以用来检验是否符合那个模式和使用Swarm hash值来取回文件。
使用自动接口生成和NatSpec
元数据通过以下方式使用:一个组件想要跟合约互动(例如,mist)获取合约的代码,用所取回文件的Swarm hash值。那个文件时JSON编码的结构化数据,如上所述。
然后组件可以使用ABI来自动生成合约的基本用户界面。
另外,当用户操作合约的时候,Mist可以用userdoc来显示确认信息。
使用源码验证
为了验证兼容性,源码可以通过元数据文件的hash,从Swarm中取回。正确的编译器版本(将会检验是否是官方编译器的版本)会被调用,并输入指定的设置。最后的字节码会和创建交易的数据或者CREATE操作码数据相比较。这会自动验证元数据,因为hash是字节码的一部分。构造函数的输入对应的其他数据,应该根据接口被解码并呈现给用户。
提示和技巧
- 对数组使用
delete
会删除它的所有数据 - 对结构体元素使用更短的类型并排序,这样有利于压缩短的数据。这可以减小gas消耗,因为多个SSTORE操作可能合成一个操作(SSTORE消耗5000或者20000gas,所以这是你期望优化的)。使用价格预估函数(且使用优化器)来检测。
- 使状态变量声明为共有-编译器会自动为其生成getters
- 如果你在函数开头写了大量的代码,用来检验输入或者状态,尝试使用函数修改器
- 如果你的合约有
send
函数,但是你想使用内建的send
函数,使用address(contractVariable).send(amount)
来调用。 - 在一个赋值表达式中,对storage结构体初始化:
x = MyStruct({a: 1, b: 2})
表格
操作码优先级
以下是操作码的优先级,根据执行顺序罗列出来。
优先级 | 描述 | 操作码 | ||
---|---|---|---|---|
1 | 后置自加或者自减 |
++ ,--
|
||
1 | New表达式 | new <typename> |
||
1 | 数组下标 | <array>[<index>] |
||
1 | 访问成员 | <object>.<member> |
||
1 | 函数形式调用 | <func>(<args...>) |
||
1 | 圆括号 | (<statement>) |
||
2 | 前置自加和自减 |
++ ,--
|
||
2 | 一元加和减法 |
+ ,-
|
||
2 | 一元操作码 | delete |
||
2 | 逻辑非 | ! |
||
2 | 按位反 | ~ |
||
3 | 指数 | ** |
||
4 | 乘法,除法和取摸 |
* ,/ ,%
|
||
5 | 加法和减法 |
+ ,-
|
||
6 | 位移操作 |
<< ,>>
|
||
7 | 按位与 | & |
||
8 | 按位异或 | ^ |
||
9 | 按位或 | ` | ` | |
10 | 非等操作符 |
< ,> ,<= ,>=
|
||
11 | 等号操作符 |
== ,!=
|
||
12 | 逻辑与 | && |
||
13 | 逻辑或 | ` | ` | |
14 | 三元操作符 | <conditional> ? <if-true> : <if-false> |
||
15 | 赋值操作符 |
= ,` |
=, ^=, &=, <<=, >>=, +=, -=, *=, /=, %=` |
|
16 | 点操作符 | . |
全局变量
-
block.blockhash(uint blockNumber) returns (bytes32)
:获取给定区块号的hash值-只对最近的256块有效。 -
block.coinbase
(address
)`:当前区块的矿工地址 -
block.difficulty
(uint
)`:当前区块的难度 -
block.gaslimit
(uint
)`:当前区块的gas限制 -
block.number
(uint
)`:当前区块的区块号 -
block.timestamp
(uint
)`:当前区块的时间戳 -
msg.data
(bytes
)`:完整的调用数据calldata -
msg.gas
(uint
)`:剩余gas -
msg.sendet
(address
)`:消息的发送方(当前调用) -
msg.value(
uint)
:消息发送的wei数量 -
now(
uint)
:当前区块的时间戳(block.timestamp
的别名) -
tx.gasprice
(uint
)`:交易的gas价格 -
tx.origin
(uint
)`:交易的发送方(整个调用链) -
assert(bool condition)
:如果条件为false,中断执行并撤销修改(用于内部错误) -
require(bool condition)
:如果条件为false,中断执行并撤销修改(用于不合预期的输入和外部组件的错误) -
revert()
:中断执行并撤销修改 -
keccak256(...) returns (bytes32)
:计算(打包好的)参数的Ethereum-SHA-3(Keccak-256)哈希 -
sha3(...) returns (bytes32)
:keccak256()的别名 -
sha256(...) returns (bytes)
:计算(打包好的)参数的SHA-256 哈希值 -
ripemd160(...) returns (bytes20)
:计算(打包好的)参数的RIPEMD-160 哈希值 -
ecrecover(bytes32 hash, uint8 v, bytes32 r,bytes32 s) returns (address)
:返回地址和公钥相关的椭圆曲线签名,如果出错返回0 -
addmod(uint x, uint y, uint k) returns (uint)
:计算(x + y) % k
,其中加法的精度可以是任意的,不会再2 ** 256
之内截断 -
mulmod(uint x, uint y, uint k) returns (uint)
:计算(x * y) % k
,其中乘法的精度可以是任意的,不会再2 ** 256
之内截断 -
this
(当前合约的类型):当前合约,可以显式转换为address
-
super
:合约的继承性的上一级 -
selfdestruct(address recipient)
:销毁当前合约,发送剩余钱币到指定地址 -
<address>.balance
(uint256
)`:地址的余额,单位为wei -
<address>.send(uint256 amount) returns (bool)
:发送指定金额(单位为wei)到指定地址,如果失败返回false
-
<address>.transfer(uint256 amount)
:发送指定金额(单位为wei)到指定地址,如果失败抛出异常
函数可见性指定
function myFunction() <visibility specifier> returns (bool) {
return true;
}
-
public
:内部可见和外部可见(会为状态变量生成getter函数) -
private
:只在当前合约可见 -
external
:只外部可见(只对函数而言)-例如,只能使用消息调用(通过this.func
) -
internal
:只在内部可见
修改器
-
constant
针对状态变量:除了初始化之外,不能多次赋值,不会占用内存槽 -
constant
针对函数:不允许再修改-这不是强制的 -
anoymous
针对事件:不会存储事件签名作为主题 -
indexed
针对事件参数:保存主题的参数 -
payable
针对函数:允许他们接收以太币
保留关键字
这些关键字是Solidity的保留字。他们可能在以后的版本中用到。
abstract
, after
, case
, catch
, default
, final
, in
, inline
, interface
, let
, match
, null
, of
, pure
, relocatable
, static
, switch
, try
, type
, typeof
, view
语言语法
SourceUnit = (PragmaDirective | ImportDirective | ContractDefinition)*
// Pragma actually parses anything up to the trailing ';' to be fully forward-compatible.
PragmaDirective = 'pragma' Identifier ([^;]+) ';'
ImportDirective = 'import' StringLiteral ('as' Identifier)? ';'
| 'import' ('*' | Identifier) ('as' Identifier)? 'from' StringLiteral ';'
| 'import' '{' Identifier ('as' Identifier)? ( ',' Identifier ('as' Identifier)? )* '}' 'from' StringLiteral ';'
ContractDefinition = ( 'contract' | 'library' | 'interface' ) Identifier
( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )?
'{' ContractPart* '}'
ContractPart = StateVariableDeclaration | UsingForDeclaration
| StructDefinition | ModifierDefinition | FunctionDefinition | EventDefinition | EnumDefinition
InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )?
StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' )? Identifier ('=' Expression)? ';'
UsingForDeclaration = 'using' Identifier 'for' ('*' | TypeName) ';'
StructDefinition = 'struct' Identifier '{'
( VariableDeclaration ';' (VariableDeclaration ';')* )? '}'
ModifierDefinition = 'modifier' Identifier ParameterList? Block
ModifierInvocation = Identifier ( '(' ExpressionList? ')' )?
FunctionDefinition = 'function' Identifier? ParameterList
( ModifierInvocation | 'constant' | 'payable' | 'external' | 'public' | 'internal' | 'private' )*
( 'returns' ParameterList )? ( ';' | Block )
EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';'
EnumValue = Identifier
EnumDefinition = 'enum' Identifier '{' EnumValue? (',' EnumValue)* '}'
IndexedParameterList = '(' ( TypeName 'indexed'? Identifier? (',' TypeName 'indexed'? Identifier?)* )? ')'
ParameterList = '(' ( TypeName Identifier? (',' TypeName Identifier?)* )? ')'
TypeNameList = '(' ( TypeName (',' TypeName )* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists
VariableDeclaration = TypeName StorageLocation? Identifier
TypeName = ElementaryTypeName
| UserDefinedTypeName
| Mapping
| ArrayTypeName
| FunctionTypeName
UserDefinedTypeName = Identifier ( '.' Identifier )*
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
ArrayTypeName = TypeName '[' Expression? ']'
FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )*
( 'returns' TypeNameList )?
StorageLocation = 'memory' | 'storage'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
( DoWhileStatement | PlaceholderStatement | Continue | Break | Return |
Throw | SimpleStatement ) ';'
ExpressionStatement = Expression
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
WhileStatement = 'while' '(' Expression ')' Statement
PlaceholderStatement = '_'
SimpleStatement = VariableDefinition | ExpressionStatement
ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement
InlineAssemblyStatement = 'assembly' StringLiteral? InlineAssemblyBlock
DoWhileStatement = 'do' Statement 'while' '(' Expression ')'
Continue = 'continue'
Break = 'break'
Return = 'return' Expression?
Throw = 'throw'
VariableDefinition = ('var' IdentifierList | VariableDeclaration) ( '=' Expression )?
IdentifierList = '(' ( Identifier? ',' )* Identifier? ')'
// Precedence by order (see github.com/ethereum/solidity/pull/732)
Expression
= Expression ('++' | '--')
| NewExpression
| IndexAccess
| MemberAccess
| FunctionCall
| '(' Expression ')'
| ('!' | '~' | 'delete' | '++' | '--' | '+' | '-') Expression
| Expression '**' Expression
| Expression ('*' | '/' | '%') Expression
| Expression ('+' | '-') Expression
| Expression ('<<' | '>>') Expression
| Expression '&' Expression
| Expression '^' Expression
| Expression '|' Expression
| Expression ('<' | '>' | '<=' | '>=') Expression
| Expression ('==' | '!=') Expression
| Expression '&&' Expression
| Expression '||' Expression
| Expression '?' Expression ':' Expression
| Expression ('=' | '|=' | '^=' | '&=' | '<<=' | '>>=' | '+=' | '-=' | '*=' | '/=' | '%=') Expression
| PrimaryExpression
PrimaryExpression = BooleanLiteral
| NumberLiteral
| HexLiteral
| StringLiteral
| TupleExpression
| Identifier
| ElementaryTypeNameExpression
ExpressionList = Expression ( ',' Expression )*
NameValueList = Identifier ':' Expression ( ',' Identifier ':' Expression )*
FunctionCall = Expression '(' FunctionCallArguments ')'
FunctionCallArguments = '{' NameValueList? '}'
| ExpressionList?
NewExpression = 'new' TypeName
MemberAccess = Expression '.' Identifier
IndexAccess = Expression '[' Expression? ']'
BooleanLiteral = 'true' | 'false'
NumberLiteral = ( HexNumber | DecimalNumber ) (' ' NumberUnit)?
NumberUnit = 'wei' | 'szabo' | 'finney' | 'ether'
| 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years'
HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]*
HexNumber = '0x' [0-9a-fA-F]+
DecimalNumber = [0-9]+
TupleExpression = '(' ( Expression ( ',' Expression )* )? ')'
| '[' ( Expression ( ',' Expression )* )? ']'
ElementaryTypeNameExpression = ElementaryTypeName
ElementaryTypeName = 'address' | 'bool' | 'string' | 'var'
| Int | Uint | Byte | Fixed | Ufixed
Int = 'int' | 'int8' | 'int16' | 'int24' | 'int32' | 'int40' | 'int48' | 'int56' | 'int64' | 'int72' | 'int80' | 'int88' | 'int96' | 'int104' | 'int112' | 'int120' | 'int128' | 'int136' | 'int144' | 'int152' | 'int160' | 'int168' | 'int176' | 'int184' | 'int192' | 'int200' | 'int208' | 'int216' | 'int224' | 'int232' | 'int240' | 'int248' | 'int256'
Uint = 'uint' | 'uint8' | 'uint16' | 'uint24' | 'uint32' | 'uint40' | 'uint48' | 'uint56' | 'uint64' | 'uint72' | 'uint80' | 'uint88' | 'uint96' | 'uint104' | 'uint112' | 'uint120' | 'uint128' | 'uint136' | 'uint144' | 'uint152' | 'uint160' | 'uint168' | 'uint176' | 'uint184' | 'uint192' | 'uint200' | 'uint208' | 'uint216' | 'uint224' | 'uint232' | 'uint240' | 'uint248' | 'uint256'
Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | 'bytes6' | 'bytes7' | 'bytes8' | 'bytes9' | 'bytes10' | 'bytes11' | 'bytes12' | 'bytes13' | 'bytes14' | 'bytes15' | 'bytes16' | 'bytes17' | 'bytes18' | 'bytes19' | 'bytes20' | 'bytes21' | 'bytes22' | 'bytes23' | 'bytes24' | 'bytes25' | 'bytes26' | 'bytes27' | 'bytes28' | 'bytes29' | 'bytes30' | 'bytes31' | 'bytes32'
Fixed = 'fixed' | 'fixed0x8' | 'fixed0x16' | 'fixed0x24' | 'fixed0x32' | 'fixed0x40' | 'fixed0x48' | 'fixed0x56' | 'fixed0x64' | 'fixed0x72' | 'fixed0x80' | 'fixed0x88' | 'fixed0x96' | 'fixed0x104' | 'fixed0x112' | 'fixed0x120' | 'fixed0x128' | 'fixed0x136' | 'fixed0x144' | 'fixed0x152' | 'fixed0x160' | 'fixed0x168' | 'fixed0x176' | 'fixed0x184' | 'fixed0x192' | 'fixed0x200' | 'fixed0x208' | 'fixed0x216' | 'fixed0x224' | 'fixed0x232' | 'fixed0x240' | 'fixed0x248' | 'fixed0x256' | 'fixed8x8' | 'fixed8x16' | 'fixed8x24' | 'fixed8x32' | 'fixed8x40' | 'fixed8x48' | 'fixed8x56' | 'fixed8x64' | 'fixed8x72' | 'fixed8x80' | 'fixed8x88' | 'fixed8x96' | 'fixed8x104' | 'fixed8x112' | 'fixed8x120' | 'fixed8x128' | 'fixed8x136' | 'fixed8x144' | 'fixed8x152' | 'fixed8x160' | 'fixed8x168' | 'fixed8x176' | 'fixed8x184' | 'fixed8x192' | 'fixed8x200' | 'fixed8x208' | 'fixed8x216' | 'fixed8x224' | 'fixed8x232' | 'fixed8x240' | 'fixed8x248' | 'fixed16x8' | 'fixed16x16' | 'fixed16x24' | 'fixed16x32' | 'fixed16x40' | 'fixed16x48' | 'fixed16x56' | 'fixed16x64' | 'fixed16x72' | 'fixed16x80' | 'fixed16x88' | 'fixed16x96' | 'fixed16x104' | 'fixed16x112' | 'fixed16x120' | 'fixed16x128' | 'fixed16x136' | 'fixed16x144' | 'fixed16x152' | 'fixed16x160' | 'fixed16x168' | 'fixed16x176' | 'fixed16x184' | 'fixed16x192' | 'fixed16x200' | 'fixed16x208' | 'fixed16x216' | 'fixed16x224' | 'fixed16x232' | 'fixed16x240' | 'fixed24x8' | 'fixed24x16' | 'fixed24x24' | 'fixed24x32' | 'fixed24x40' | 'fixed24x48' | 'fixed24x56' | 'fixed24x64' | 'fixed24x72' | 'fixed24x80' | 'fixed24x88' | 'fixed24x96' | 'fixed24x104' | 'fixed24x112' | 'fixed24x120' | 'fixed24x128' | 'fixed24x136' | 'fixed24x144' | 'fixed24x152' | 'fixed24x160' | 'fixed24x168' | 'fixed24x176' | 'fixed24x184' | 'fixed24x192' | 'fixed24x200' | 'fixed24x208' | 'fixed24x216' | 'fixed24x224' | 'fixed24x232' | 'fixed32x8' | 'fixed32x16' | 'fixed32x24' | 'fixed32x32' | 'fixed32x40' | 'fixed32x48' | 'fixed32x56' | 'fixed32x64' | 'fixed32x72' | 'fixed32x80' | 'fixed32x88' | 'fixed32x96' | 'fixed32x104' | 'fixed32x112' | 'fixed32x120' | 'fixed32x128' | 'fixed32x136' | 'fixed32x144' | 'fixed32x152' | 'fixed32x160' | 'fixed32x168' | 'fixed32x176' | 'fixed32x184' | 'fixed32x192' | 'fixed32x200' | 'fixed32x208' | 'fixed32x216' | 'fixed32x224' | 'fixed40x8' | 'fixed40x16' | 'fixed40x24' | 'fixed40x32' | 'fixed40x40' | 'fixed40x48' | 'fixed40x56' | 'fixed40x64' | 'fixed40x72' | 'fixed40x80' | 'fixed40x88' | 'fixed40x96' | 'fixed40x104' | 'fixed40x112' | 'fixed40x120' | 'fixed40x128' | 'fixed40x136' | 'fixed40x144' | 'fixed40x152' | 'fixed40x160' | 'fixed40x168' | 'fixed40x176' | 'fixed40x184' | 'fixed40x192' | 'fixed40x200' | 'fixed40x208' | 'fixed40x216' | 'fixed48x8' | 'fixed48x16' | 'fixed48x24' | 'fixed48x32' | 'fixed48x40' | 'fixed48x48' | 'fixed48x56' | 'fixed48x64' | 'fixed48x72' | 'fixed48x80' | 'fixed48x88' | 'fixed48x96' | 'fixed48x104' | 'fixed48x112' | 'fixed48x120' | 'fixed48x128' | 'fixed48x136' | 'fixed48x144' | 'fixed48x152' | 'fixed48x160' | 'fixed48x168' | 'fixed48x176' | 'fixed48x184' | 'fixed48x192' | 'fixed48x200' | 'fixed48x208' | 'fixed56x8' | 'fixed56x16' | 'fixed56x24' | 'fixed56x32' | 'fixed56x40' | 'fixed56x48' | 'fixed56x56' | 'fixed56x64' | 'fixed56x72' | 'fixed56x80' | 'fixed56x88' | 'fixed56x96' | 'fixed56x104' | 'fixed56x112' | 'fixed56x120' | 'fixed56x128' | 'fixed56x136' | 'fixed56x144' | 'fixed56x152' | 'fixed56x160' | 'fixed56x168' | 'fixed56x176' | 'fixed56x184' | 'fixed56x192' | 'fixed56x200' | 'fixed64x8' | 'fixed64x16' | 'fixed64x24' | 'fixed64x32' | 'fixed64x40' | 'fixed64x48' | 'fixed64x56' | 'fixed64x64' | 'fixed64x72' | 'fixed64x80' | 'fixed64x88' | 'fixed64x96' | 'fixed64x104' | 'fixed64x112' | 'fixed64x120' | 'fixed64x128' | 'fixed64x136' | 'fixed64x144' | 'fixed64x152' | 'fixed64x160' | 'fixed64x168' | 'fixed64x176' | 'fixed64x184' | 'fixed64x192' | 'fixed72x8' | 'fixed72x16' | 'fixed72x24' | 'fixed72x32' | 'fixed72x40' | 'fixed72x48' | 'fixed72x56' | 'fixed72x64' | 'fixed72x72' | 'fixed72x80' | 'fixed72x88' | 'fixed72x96' | 'fixed72x104' | 'fixed72x112' | 'fixed72x120' | 'fixed72x128' | 'fixed72x136' | 'fixed72x144' | 'fixed72x152' | 'fixed72x160' | 'fixed72x168' | 'fixed72x176' | 'fixed72x184' | 'fixed80x8' | 'fixed80x16' | 'fixed80x24' | 'fixed80x32' | 'fixed80x40' | 'fixed80x48' | 'fixed80x56' | 'fixed80x64' | 'fixed80x72' | 'fixed80x80' | 'fixed80x88' | 'fixed80x96' | 'fixed80x104' | 'fixed80x112' | 'fixed80x120' | 'fixed80x128' | 'fixed80x136' | 'fixed80x144' | 'fixed80x152' | 'fixed80x160' | 'fixed80x168' | 'fixed80x176' | 'fixed88x8' | 'fixed88x16' | 'fixed88x24' | 'fixed88x32' | 'fixed88x40' | 'fixed88x48' | 'fixed88x56' | 'fixed88x64' | 'fixed88x72' | 'fixed88x80' | 'fixed88x88' | 'fixed88x96' | 'fixed88x104' | 'fixed88x112' | 'fixed88x120' | 'fixed88x128' | 'fixed88x136' | 'fixed88x144' | 'fixed88x152' | 'fixed88x160' | 'fixed88x168' | 'fixed96x8' | 'fixed96x16' | 'fixed96x24' | 'fixed96x32' | 'fixed96x40' | 'fixed96x48' | 'fixed96x56' | 'fixed96x64' | 'fixed96x72' | 'fixed96x80' | 'fixed96x88' | 'fixed96x96' | 'fixed96x104' | 'fixed96x112' | 'fixed96x120' | 'fixed96x128' | 'fixed96x136' | 'fixed96x144' | 'fixed96x152' | 'fixed96x160' | 'fixed104x8' | 'fixed104x16' | 'fixed104x24' | 'fixed104x32' | 'fixed104x40' | 'fixed104x48' | 'fixed104x56' | 'fixed104x64' | 'fixed104x72' | 'fixed104x80' | 'fixed104x88' | 'fixed104x96' | 'fixed104x104' | 'fixed104x112' | 'fixed104x120' | 'fixed104x128' | 'fixed104x136' | 'fixed104x144' | 'fixed104x152' | 'fixed112x8' | 'fixed112x16' | 'fixed112x24' | 'fixed112x32' | 'fixed112x40' | 'fixed112x48' | 'fixed112x56' | 'fixed112x64' | 'fixed112x72' | 'fixed112x80' | 'fixed112x88' | 'fixed112x96' | 'fixed112x104' | 'fixed112x112' | 'fixed112x120' | 'fixed112x128' | 'fixed112x136' | 'fixed112x144' | 'fixed120x8' | 'fixed120x16' | 'fixed120x24' | 'fixed120x32' | 'fixed120x40' | 'fixed120x48' | 'fixed120x56' | 'fixed120x64' | 'fixed120x72' | 'fixed120x80' | 'fixed120x88' | 'fixed120x96' | 'fixed120x104' | 'fixed120x112' | 'fixed120x120' | 'fixed120x128' | 'fixed120x136' | 'fixed128x8' | 'fixed128x16' | 'fixed128x24' | 'fixed128x32' | 'fixed128x40' | 'fixed128x48' | 'fixed128x56' | 'fixed128x64' | 'fixed128x72' | 'fixed128x80' | 'fixed128x88' | 'fixed128x96' | 'fixed128x104' | 'fixed128x112' | 'fixed128x120' | 'fixed128x128' | 'fixed136x8' | 'fixed136x16' | 'fixed136x24' | 'fixed136x32' | 'fixed136x40' | 'fixed136x48' | 'fixed136x56' | 'fixed136x64' | 'fixed136x72' | 'fixed136x80' | 'fixed136x88' | 'fixed136x96' | 'fixed136x104' | 'fixed136x112' | 'fixed136x120' | 'fixed144x8' | 'fixed144x16' | 'fixed144x24' | 'fixed144x32' | 'fixed144x40' | 'fixed144x48' | 'fixed144x56' | 'fixed144x64' | 'fixed144x72' | 'fixed144x80' | 'fixed144x88' | 'fixed144x96' | 'fixed144x104' | 'fixed144x112' | 'fixed152x8' | 'fixed152x16' | 'fixed152x24' | 'fixed152x32' | 'fixed152x40' | 'fixed152x48' | 'fixed152x56' | 'fixed152x64' | 'fixed152x72' | 'fixed152x80' | 'fixed152x88' | 'fixed152x96' | 'fixed152x104' | 'fixed160x8' | 'fixed160x16' | 'fixed160x24' | 'fixed160x32' | 'fixed160x40' | 'fixed160x48' | 'fixed160x56' | 'fixed160x64' | 'fixed160x72' | 'fixed160x80' | 'fixed160x88' | 'fixed160x96' | 'fixed168x8' | 'fixed168x16' | 'fixed168x24' | 'fixed168x32' | 'fixed168x40' | 'fixed168x48' | 'fixed168x56' | 'fixed168x64' | 'fixed168x72' | 'fixed168x80' | 'fixed168x88' | 'fixed176x8' | 'fixed176x16' | 'fixed176x24' | 'fixed176x32' | 'fixed176x40' | 'fixed176x48' | 'fixed176x56' | 'fixed176x64' | 'fixed176x72' | 'fixed176x80' | 'fixed184x8' | 'fixed184x16' | 'fixed184x24' | 'fixed184x32' | 'fixed184x40' | 'fixed184x48' | 'fixed184x56' | 'fixed184x64' | 'fixed184x72' | 'fixed192x8' | 'fixed192x16' | 'fixed192x24' | 'fixed192x32' | 'fixed192x40' | 'fixed192x48' | 'fixed192x56' | 'fixed192x64' | 'fixed200x8' | 'fixed200x16' | 'fixed200x24' | 'fixed200x32' | 'fixed200x40' | 'fixed200x48' | 'fixed200x56' | 'fixed208x8' | 'fixed208x16' | 'fixed208x24' | 'fixed208x32' | 'fixed208x40' | 'fixed208x48' | 'fixed216x8' | 'fixed216x16' | 'fixed216x24' | 'fixed216x32' | 'fixed216x40' | 'fixed224x8' | 'fixed224x16' | 'fixed224x24' | 'fixed224x32' | 'fixed232x8' | 'fixed232x16' | 'fixed232x24' | 'fixed240x8' | 'fixed240x16' | 'fixed248x8'
Ufixed = 'ufixed' | 'ufixed0x8' | 'ufixed0x16' | 'ufixed0x24' | 'ufixed0x32' | 'ufixed0x40' | 'ufixed0x48' | 'ufixed0x56' | 'ufixed0x64' | 'ufixed0x72' | 'ufixed0x80' | 'ufixed0x88' | 'ufixed0x96' | 'ufixed0x104' | 'ufixed0x112' | 'ufixed0x120' | 'ufixed0x128' | 'ufixed0x136' | 'ufixed0x144' | 'ufixed0x152' | 'ufixed0x160' | 'ufixed0x168' | 'ufixed0x176' | 'ufixed0x184' | 'ufixed0x192' | 'ufixed0x200' | 'ufixed0x208' | 'ufixed0x216' | 'ufixed0x224' | 'ufixed0x232' | 'ufixed0x240' | 'ufixed0x248' | 'ufixed0x256' | 'ufixed8x8' | 'ufixed8x16' | 'ufixed8x24' | 'ufixed8x32' | 'ufixed8x40' | 'ufixed8x48' | 'ufixed8x56' | 'ufixed8x64' | 'ufixed8x72' | 'ufixed8x80' | 'ufixed8x88' | 'ufixed8x96' | 'ufixed8x104' | 'ufixed8x112' | 'ufixed8x120' | 'ufixed8x128' | 'ufixed8x136' | 'ufixed8x144' | 'ufixed8x152' | 'ufixed8x160' | 'ufixed8x168' | 'ufixed8x176' | 'ufixed8x184' | 'ufixed8x192' | 'ufixed8x200' | 'ufixed8x208' | 'ufixed8x216' | 'ufixed8x224' | 'ufixed8x232' | 'ufixed8x240' | 'ufixed8x248' | 'ufixed16x8' | 'ufixed16x16' | 'ufixed16x24' | 'ufixed16x32' | 'ufixed16x40' | 'ufixed16x48' | 'ufixed16x56' | 'ufixed16x64' | 'ufixed16x72' | 'ufixed16x80' | 'ufixed16x88' | 'ufixed16x96' | 'ufixed16x104' | 'ufixed16x112' | 'ufixed16x120' | 'ufixed16x128' | 'ufixed16x136' | 'ufixed16x144' | 'ufixed16x152' | 'ufixed16x160' | 'ufixed16x168' | 'ufixed16x176' | 'ufixed16x184' | 'ufixed16x192' | 'ufixed16x200' | 'ufixed16x208' | 'ufixed16x216' | 'ufixed16x224' | 'ufixed16x232' | 'ufixed16x240' | 'ufixed24x8' | 'ufixed24x16' | 'ufixed24x24' | 'ufixed24x32' | 'ufixed24x40' | 'ufixed24x48' | 'ufixed24x56' | 'ufixed24x64' | 'ufixed24x72' | 'ufixed24x80' | 'ufixed24x88' | 'ufixed24x96' | 'ufixed24x104' | 'ufixed24x112' | 'ufixed24x120' | 'ufixed24x128' | 'ufixed24x136' | 'ufixed24x144' | 'ufixed24x152' | 'ufixed24x160' | 'ufixed24x168' | 'ufixed24x176' | 'ufixed24x184' | 'ufixed24x192' | 'ufixed24x200' | 'ufixed24x208' | 'ufixed24x216' | 'ufixed24x224' | 'ufixed24x232' | 'ufixed32x8' | 'ufixed32x16' | 'ufixed32x24' | 'ufixed32x32' | 'ufixed32x40' | 'ufixed32x48' | 'ufixed32x56' | 'ufixed32x64' | 'ufixed32x72' | 'ufixed32x80' | 'ufixed32x88' | 'ufixed32x96' | 'ufixed32x104' | 'ufixed32x112' | 'ufixed32x120' | 'ufixed32x128' | 'ufixed32x136' | 'ufixed32x144' | 'ufixed32x152' | 'ufixed32x160' | 'ufixed32x168' | 'ufixed32x176' | 'ufixed32x184' | 'ufixed32x192' | 'ufixed32x200' | 'ufixed32x208' | 'ufixed32x216' | 'ufixed32x224' | 'ufixed40x8' | 'ufixed40x16' | 'ufixed40x24' | 'ufixed40x32' | 'ufixed40x40' | 'ufixed40x48' | 'ufixed40x56' | 'ufixed40x64' | 'ufixed40x72' | 'ufixed40x80' | 'ufixed40x88' | 'ufixed40x96' | 'ufixed40x104' | 'ufixed40x112' | 'ufixed40x120' | 'ufixed40x128' | 'ufixed40x136' | 'ufixed40x144' | 'ufixed40x152' | 'ufixed40x160' | 'ufixed40x168' | 'ufixed40x176' | 'ufixed40x184' | 'ufixed40x192' | 'ufixed40x200' | 'ufixed40x208' | 'ufixed40x216' | 'ufixed48x8' | 'ufixed48x16' | 'ufixed48x24' | 'ufixed48x32' | 'ufixed48x40' | 'ufixed48x48' | 'ufixed48x56' | 'ufixed48x64' | 'ufixed48x72' | 'ufixed48x80' | 'ufixed48x88' | 'ufixed48x96' | 'ufixed48x104' | 'ufixed48x112' | 'ufixed48x120' | 'ufixed48x128' | 'ufixed48x136' | 'ufixed48x144' | 'ufixed48x152' | 'ufixed48x160' | 'ufixed48x168' | 'ufixed48x176' | 'ufixed48x184' | 'ufixed48x192' | 'ufixed48x200' | 'ufixed48x208' | 'ufixed56x8' | 'ufixed56x16' | 'ufixed56x24' | 'ufixed56x32' | 'ufixed56x40' | 'ufixed56x48' | 'ufixed56x56' | 'ufixed56x64' | 'ufixed56x72' | 'ufixed56x80' | 'ufixed56x88' | 'ufixed56x96' | 'ufixed56x104' | 'ufixed56x112' | 'ufixed56x120' | 'ufixed56x128' | 'ufixed56x136' | 'ufixed56x144' | 'ufixed56x152' | 'ufixed56x160' | 'ufixed56x168' | 'ufixed56x176' | 'ufixed56x184' | 'ufixed56x192' | 'ufixed56x200' | 'ufixed64x8' | 'ufixed64x16' | 'ufixed64x24' | 'ufixed64x32' | 'ufixed64x40' | 'ufixed64x48' | 'ufixed64x56' | 'ufixed64x64' | 'ufixed64x72' | 'ufixed64x80' | 'ufixed64x88' | 'ufixed64x96' | 'ufixed64x104' | 'ufixed64x112' | 'ufixed64x120' | 'ufixed64x128' | 'ufixed64x136' | 'ufixed64x144' | 'ufixed64x152' | 'ufixed64x160' | 'ufixed64x168' | 'ufixed64x176' | 'ufixed64x184' | 'ufixed64x192' | 'ufixed72x8' | 'ufixed72x16' | 'ufixed72x24' | 'ufixed72x32' | 'ufixed72x40' | 'ufixed72x48' | 'ufixed72x56' | 'ufixed72x64' | 'ufixed72x72' | 'ufixed72x80' | 'ufixed72x88' | 'ufixed72x96' | 'ufixed72x104' | 'ufixed72x112' | 'ufixed72x120' | 'ufixed72x128' | 'ufixed72x136' | 'ufixed72x144' | 'ufixed72x152' | 'ufixed72x160' | 'ufixed72x168' | 'ufixed72x176' | 'ufixed72x184' | 'ufixed80x8' | 'ufixed80x16' | 'ufixed80x24' | 'ufixed80x32' | 'ufixed80x40' | 'ufixed80x48' | 'ufixed80x56' | 'ufixed80x64' | 'ufixed80x72' | 'ufixed80x80' | 'ufixed80x88' | 'ufixed80x96' | 'ufixed80x104' | 'ufixed80x112' | 'ufixed80x120' | 'ufixed80x128' | 'ufixed80x136' | 'ufixed80x144' | 'ufixed80x152' | 'ufixed80x160' | 'ufixed80x168' | 'ufixed80x176' | 'ufixed88x8' | 'ufixed88x16' | 'ufixed88x24' | 'ufixed88x32' | 'ufixed88x40' | 'ufixed88x48' | 'ufixed88x56' | 'ufixed88x64' | 'ufixed88x72' | 'ufixed88x80' | 'ufixed88x88' | 'ufixed88x96' | 'ufixed88x104' | 'ufixed88x112' | 'ufixed88x120' | 'ufixed88x128' | 'ufixed88x136' | 'ufixed88x144' | 'ufixed88x152' | 'ufixed88x160' | 'ufixed88x168' | 'ufixed96x8' | 'ufixed96x16' | 'ufixed96x24' | 'ufixed96x32' | 'ufixed96x40' | 'ufixed96x48' | 'ufixed96x56' | 'ufixed96x64' | 'ufixed96x72' | 'ufixed96x80' | 'ufixed96x88' | 'ufixed96x96' | 'ufixed96x104' | 'ufixed96x112' | 'ufixed96x120' | 'ufixed96x128' | 'ufixed96x136' | 'ufixed96x144' | 'ufixed96x152' | 'ufixed96x160' | 'ufixed104x8' | 'ufixed104x16' | 'ufixed104x24' | 'ufixed104x32' | 'ufixed104x40' | 'ufixed104x48' | 'ufixed104x56' | 'ufixed104x64' | 'ufixed104x72' | 'ufixed104x80' | 'ufixed104x88' | 'ufixed104x96' | 'ufixed104x104' | 'ufixed104x112' | 'ufixed104x120' | 'ufixed104x128' | 'ufixed104x136' | 'ufixed104x144' | 'ufixed104x152' | 'ufixed112x8' | 'ufixed112x16' | 'ufixed112x24' | 'ufixed112x32' | 'ufixed112x40' | 'ufixed112x48' | 'ufixed112x56' | 'ufixed112x64' | 'ufixed112x72' | 'ufixed112x80' | 'ufixed112x88' | 'ufixed112x96' | 'ufixed112x104' | 'ufixed112x112' | 'ufixed112x120' | 'ufixed112x128' | 'ufixed112x136' | 'ufixed112x144' | 'ufixed120x8' | 'ufixed120x16' | 'ufixed120x24' | 'ufixed120x32' | 'ufixed120x40' | 'ufixed120x48' | 'ufixed120x56' | 'ufixed120x64' | 'ufixed120x72' | 'ufixed120x80' | 'ufixed120x88' | 'ufixed120x96' | 'ufixed120x104' | 'ufixed120x112' | 'ufixed120x120' | 'ufixed120x128' | 'ufixed120x136' | 'ufixed128x8' | 'ufixed128x16' | 'ufixed128x24' | 'ufixed128x32' | 'ufixed128x40' | 'ufixed128x48' | 'ufixed128x56' | 'ufixed128x64' | 'ufixed128x72' | 'ufixed128x80' | 'ufixed128x88' | 'ufixed128x96' | 'ufixed128x104' | 'ufixed128x112' | 'ufixed128x120' | 'ufixed128x128' | 'ufixed136x8' | 'ufixed136x16' | 'ufixed136x24' | 'ufixed136x32' | 'ufixed136x40' | 'ufixed136x48' | 'ufixed136x56' | 'ufixed136x64' | 'ufixed136x72' | 'ufixed136x80' | 'ufixed136x88' | 'ufixed136x96' | 'ufixed136x104' | 'ufixed136x112' | 'ufixed136x120' | 'ufixed144x8' | 'ufixed144x16' | 'ufixed144x24' | 'ufixed144x32' | 'ufixed144x40' | 'ufixed144x48' | 'ufixed144x56' | 'ufixed144x64' | 'ufixed144x72' | 'ufixed144x80' | 'ufixed144x88' | 'ufixed144x96' | 'ufixed144x104' | 'ufixed144x112' | 'ufixed152x8' | 'ufixed152x16' | 'ufixed152x24' | 'ufixed152x32' | 'ufixed152x40' | 'ufixed152x48' | 'ufixed152x56' | 'ufixed152x64' | 'ufixed152x72' | 'ufixed152x80' | 'ufixed152x88' | 'ufixed152x96' | 'ufixed152x104' | 'ufixed160x8' | 'ufixed160x16' | 'ufixed160x24' | 'ufixed160x32' | 'ufixed160x40' | 'ufixed160x48' | 'ufixed160x56' | 'ufixed160x64' | 'ufixed160x72' | 'ufixed160x80' | 'ufixed160x88' | 'ufixed160x96' | 'ufixed168x8' | 'ufixed168x16' | 'ufixed168x24' | 'ufixed168x32' | 'ufixed168x40' | 'ufixed168x48' | 'ufixed168x56' | 'ufixed168x64' | 'ufixed168x72' | 'ufixed168x80' | 'ufixed168x88' | 'ufixed176x8' | 'ufixed176x16' | 'ufixed176x24' | 'ufixed176x32' | 'ufixed176x40' | 'ufixed176x48' | 'ufixed176x56' | 'ufixed176x64' | 'ufixed176x72' | 'ufixed176x80' | 'ufixed184x8' | 'ufixed184x16' | 'ufixed184x24' | 'ufixed184x32' | 'ufixed184x40' | 'ufixed184x48' | 'ufixed184x56' | 'ufixed184x64' | 'ufixed184x72' | 'ufixed192x8' | 'ufixed192x16' | 'ufixed192x24' | 'ufixed192x32' | 'ufixed192x40' | 'ufixed192x48' | 'ufixed192x56' | 'ufixed192x64' | 'ufixed200x8' | 'ufixed200x16' | 'ufixed200x24' | 'ufixed200x32' | 'ufixed200x40' | 'ufixed200x48' | 'ufixed200x56' | 'ufixed208x8' | 'ufixed208x16' | 'ufixed208x24' | 'ufixed208x32' | 'ufixed208x40' | 'ufixed208x48' | 'ufixed216x8' | 'ufixed216x16' | 'ufixed216x24' | 'ufixed216x32' | 'ufixed216x40' | 'ufixed224x8' | 'ufixed224x16' | 'ufixed224x24' | 'ufixed224x32' | 'ufixed232x8' | 'ufixed232x16' | 'ufixed232x24' | 'ufixed240x8' | 'ufixed240x16' | 'ufixed248x8'
InlineAssemblyBlock = '{' AssemblyItem* '}'
AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | AssemblyLabel | NumberLiteral | StringLiteral | HexLiteral
AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression
AssemblyAssignment = ( Identifier ':=' FunctionalAssemblyExpression ) | ( '=:' Identifier )
AssemblyLabel = Identifier ':'
FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')'