blob: 134afedbb7b4b80ce0f2e5bedbb0804d80f32e31 [file] [log] [blame]
Sean Silva1b600182013-01-07 02:43:44 +00001===========================
2TableGen Language Reference
3===========================
4
Sean Silva1b600182013-01-07 02:43:44 +00005.. contents::
6 :local:
7
8.. warning::
9 This document is extremely rough. If you find something lacking, please
10 fix it, file a documentation bug, or ask about it on llvmdev.
11
12Introduction
13============
14
15This document is meant to be a normative spec about the TableGen language
16in and of itself (i.e. how to understand a given construct in terms of how
17it affects the final set of records represented by the TableGen file). If
18you are unsure if this document is really what you are looking for, please
Sean Silva397ee6e2014-04-07 22:46:40 +000019read the :doc:`introduction to TableGen <index>` first.
Sean Silva1b600182013-01-07 02:43:44 +000020
Renato Golin33f973a2014-04-01 09:51:49 +000021Notation
22========
Sean Silva1b600182013-01-07 02:43:44 +000023
Renato Golin33f973a2014-04-01 09:51:49 +000024The lexical and syntax notation used here is intended to imitate
25`Python's`_. In particular, for lexical definitions, the productions
26operate at the character level and there is no implied whitespace between
27elements. The syntax definitions operate at the token level, so there is
28implied whitespace between tokens.
Sean Silva1b600182013-01-07 02:43:44 +000029
Renato Golin33f973a2014-04-01 09:51:49 +000030.. _`Python's`: http://docs.python.org/py3k/reference/introduction.html#notation
Sean Silva1b600182013-01-07 02:43:44 +000031
Renato Golin33f973a2014-04-01 09:51:49 +000032Lexical Analysis
33================
Sean Silva1b600182013-01-07 02:43:44 +000034
Renato Golin33f973a2014-04-01 09:51:49 +000035TableGen supports BCPL (``// ...``) and nestable C-style (``/* ... */``)
36comments.
Sean Silva1b600182013-01-07 02:43:44 +000037
Renato Golin33f973a2014-04-01 09:51:49 +000038The following is a listing of the basic punctuation tokens::
Sean Silva1b600182013-01-07 02:43:44 +000039
Renato Golin33f973a2014-04-01 09:51:49 +000040 - + [ ] { } ( ) < > : ; . = ? #
Sean Silva1b600182013-01-07 02:43:44 +000041
Renato Golin33f973a2014-04-01 09:51:49 +000042Numeric literals take one of the following forms:
Sean Silva1b600182013-01-07 02:43:44 +000043
Renato Golin33f973a2014-04-01 09:51:49 +000044.. TableGen actually will lex some pretty strange sequences an interpret
45 them as numbers. What is shown here is an attempt to approximate what it
46 "should" accept.
Sean Silva1b600182013-01-07 02:43:44 +000047
Renato Golin33f973a2014-04-01 09:51:49 +000048.. productionlist::
49 TokInteger: `DecimalInteger` | `HexInteger` | `BinInteger`
50 DecimalInteger: ["+" | "-"] ("0"..."9")+
51 HexInteger: "0x" ("0"..."9" | "a"..."f" | "A"..."F")+
52 BinInteger: "0b" ("0" | "1")+
Sean Silva1b600182013-01-07 02:43:44 +000053
Renato Golin33f973a2014-04-01 09:51:49 +000054One aspect to note is that the :token:`DecimalInteger` token *includes* the
55``+`` or ``-``, as opposed to having ``+`` and ``-`` be unary operators as
56most languages do.
Sean Silva1b600182013-01-07 02:43:44 +000057
Pete Cooper9b90dc72014-08-07 05:47:13 +000058Also note that :token:`BinInteger` creates a value of type ``bits<n>``
59(where ``n`` is the number of bits). This will implicitly convert to
60integers when needed.
61
Renato Golin33f973a2014-04-01 09:51:49 +000062TableGen has identifier-like tokens:
Sean Silva1b600182013-01-07 02:43:44 +000063
Renato Golin33f973a2014-04-01 09:51:49 +000064.. productionlist::
65 ualpha: "a"..."z" | "A"..."Z" | "_"
66 TokIdentifier: ("0"..."9")* `ualpha` (`ualpha` | "0"..."9")*
67 TokVarName: "$" `ualpha` (`ualpha` | "0"..."9")*
Sean Silva1b600182013-01-07 02:43:44 +000068
Renato Golin33f973a2014-04-01 09:51:49 +000069Note that unlike most languages, TableGen allows :token:`TokIdentifier` to
70begin with a number. In case of ambiguity, a token will be interpreted as a
71numeric literal rather than an identifier.
Sean Silva1b600182013-01-07 02:43:44 +000072
Renato Golin33f973a2014-04-01 09:51:49 +000073TableGen also has two string-like literals:
Sean Silva1b600182013-01-07 02:43:44 +000074
Renato Golin33f973a2014-04-01 09:51:49 +000075.. productionlist::
76 TokString: '"' <non-'"' characters and C-like escapes> '"'
77 TokCodeFragment: "[{" <shortest text not containing "}]"> "}]"
Sean Silva1b600182013-01-07 02:43:44 +000078
Renato Golin33f973a2014-04-01 09:51:49 +000079:token:`TokCodeFragment` is essentially a multiline string literal
80delimited by ``[{`` and ``}]``.
Sean Silvacc373352014-02-09 02:43:50 +000081
Renato Golin33f973a2014-04-01 09:51:49 +000082.. note::
83 The current implementation accepts the following C-like escapes::
Sean Silva543fd7f2013-01-09 02:20:30 +000084
Renato Golin33f973a2014-04-01 09:51:49 +000085 \\ \' \" \t \n
Sean Silva543fd7f2013-01-09 02:20:30 +000086
Renato Golin33f973a2014-04-01 09:51:49 +000087TableGen also has the following keywords::
Sean Silva1b600182013-01-07 02:43:44 +000088
Renato Golin33f973a2014-04-01 09:51:49 +000089 bit bits class code dag
90 def foreach defm field in
91 int let list multiclass string
Sean Silva1b600182013-01-07 02:43:44 +000092
Renato Golin33f973a2014-04-01 09:51:49 +000093TableGen also has "bang operators" which have a
94wide variety of meanings:
Sean Silva1b600182013-01-07 02:43:44 +000095
Renato Golin33f973a2014-04-01 09:51:49 +000096.. productionlist::
97 BangOperator: one of
98 :!eq !if !head !tail !con
Joerg Sonnenberger0a537272014-09-03 13:17:03 +000099 :!add !shl !sra !srl !and
Daniel Sanders314e80e2014-05-07 10:13:19 +0000100 :!cast !empty !subst !foreach !listconcat !strconcat
Sean Silva1b600182013-01-07 02:43:44 +0000101
Renato Golin33f973a2014-04-01 09:51:49 +0000102Syntax
103======
Sean Silva1b600182013-01-07 02:43:44 +0000104
Renato Golin33f973a2014-04-01 09:51:49 +0000105TableGen has an ``include`` mechanism. It does not play a role in the
106syntax per se, since it is lexically replaced with the contents of the
107included file.
Sean Silva1b600182013-01-07 02:43:44 +0000108
Renato Golin33f973a2014-04-01 09:51:49 +0000109.. productionlist::
110 IncludeDirective: "include" `TokString`
Sean Silva1b600182013-01-07 02:43:44 +0000111
Renato Golin33f973a2014-04-01 09:51:49 +0000112TableGen's top-level production consists of "objects".
Sean Silva1b600182013-01-07 02:43:44 +0000113
Renato Golin33f973a2014-04-01 09:51:49 +0000114.. productionlist::
115 TableGenFile: `Object`*
116 Object: `Class` | `Def` | `Defm` | `Let` | `MultiClass` | `Foreach`
Sean Silva1b600182013-01-07 02:43:44 +0000117
Renato Golin33f973a2014-04-01 09:51:49 +0000118``class``\es
119------------
Sean Silva1b600182013-01-07 02:43:44 +0000120
Renato Golin33f973a2014-04-01 09:51:49 +0000121.. productionlist::
122 Class: "class" `TokIdentifier` [`TemplateArgList`] `ObjectBody`
Sean Silva1b600182013-01-07 02:43:44 +0000123
Renato Golin33f973a2014-04-01 09:51:49 +0000124A ``class`` declaration creates a record which other records can inherit
125from. A class can be parametrized by a list of "template arguments", whose
126values can be used in the class body.
Sean Silva1b600182013-01-07 02:43:44 +0000127
Renato Golin33f973a2014-04-01 09:51:49 +0000128A given class can only be defined once. A ``class`` declaration is
129considered to define the class if any of the following is true:
Sean Silva1b600182013-01-07 02:43:44 +0000130
Renato Golin33f973a2014-04-01 09:51:49 +0000131.. break ObjectBody into its consituents so that they are present here?
Sean Silva1b600182013-01-07 02:43:44 +0000132
Renato Golin33f973a2014-04-01 09:51:49 +0000133#. The :token:`TemplateArgList` is present.
134#. The :token:`Body` in the :token:`ObjectBody` is present and is not empty.
135#. The :token:`BaseClassList` in the :token:`ObjectBody` is present.
Sean Silva1b600182013-01-07 02:43:44 +0000136
Renato Golin33f973a2014-04-01 09:51:49 +0000137You can declare an empty class by giving and empty :token:`TemplateArgList`
138and an empty :token:`ObjectBody`. This can serve as a restricted form of
139forward declaration: note that records deriving from the forward-declared
140class will inherit no fields from it since the record expansion is done
141when the record is parsed.
Sean Silva1b600182013-01-07 02:43:44 +0000142
Renato Golin33f973a2014-04-01 09:51:49 +0000143.. productionlist::
144 TemplateArgList: "<" `Declaration` ("," `Declaration`)* ">"
Sean Silva1b600182013-01-07 02:43:44 +0000145
Renato Golin33f973a2014-04-01 09:51:49 +0000146Declarations
147------------
Sean Silva1b600182013-01-07 02:43:44 +0000148
Renato Golin33f973a2014-04-01 09:51:49 +0000149.. Omitting mention of arcane "field" prefix to discourage its use.
Sean Silva1b600182013-01-07 02:43:44 +0000150
Renato Golin33f973a2014-04-01 09:51:49 +0000151The declaration syntax is pretty much what you would expect as a C++
152programmer.
Sean Silva1b600182013-01-07 02:43:44 +0000153
Renato Golin33f973a2014-04-01 09:51:49 +0000154.. productionlist::
155 Declaration: `Type` `TokIdentifier` ["=" `Value`]
Sean Silva1b600182013-01-07 02:43:44 +0000156
Renato Golin33f973a2014-04-01 09:51:49 +0000157It assigns the value to the identifer.
Sean Silva1b600182013-01-07 02:43:44 +0000158
Renato Golin33f973a2014-04-01 09:51:49 +0000159Types
160-----
Sean Silva1b600182013-01-07 02:43:44 +0000161
Renato Golin33f973a2014-04-01 09:51:49 +0000162.. productionlist::
163 Type: "string" | "code" | "bit" | "int" | "dag"
164 :| "bits" "<" `TokInteger` ">"
165 :| "list" "<" `Type` ">"
166 :| `ClassID`
167 ClassID: `TokIdentifier`
Sean Silva1b600182013-01-07 02:43:44 +0000168
Renato Golin33f973a2014-04-01 09:51:49 +0000169Both ``string`` and ``code`` correspond to the string type; the difference
170is purely to indicate programmer intention.
Renato Golinca105642014-03-20 16:08:34 +0000171
Renato Golin33f973a2014-04-01 09:51:49 +0000172The :token:`ClassID` must identify a class that has been previously
173declared or defined.
Renato Golinca105642014-03-20 16:08:34 +0000174
Renato Golin33f973a2014-04-01 09:51:49 +0000175Values
176------
Renato Golinca105642014-03-20 16:08:34 +0000177
Renato Golin33f973a2014-04-01 09:51:49 +0000178.. productionlist::
179 Value: `SimpleValue` `ValueSuffix`*
180 ValueSuffix: "{" `RangeList` "}"
181 :| "[" `RangeList` "]"
182 :| "." `TokIdentifier`
183 RangeList: `RangePiece` ("," `RangePiece`)*
184 RangePiece: `TokInteger`
185 :| `TokInteger` "-" `TokInteger`
186 :| `TokInteger` `TokInteger`
Renato Golinca105642014-03-20 16:08:34 +0000187
Renato Golin33f973a2014-04-01 09:51:49 +0000188The peculiar last form of :token:`RangePiece` is due to the fact that the
189"``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as
190two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``,
191instead of "1", "-", and "5".
192The :token:`RangeList` can be thought of as specifying "list slice" in some
193contexts.
Renato Golinca105642014-03-20 16:08:34 +0000194
Renato Golinca105642014-03-20 16:08:34 +0000195
Renato Golin33f973a2014-04-01 09:51:49 +0000196:token:`SimpleValue` has a number of forms:
Renato Golinca105642014-03-20 16:08:34 +0000197
Renato Golinca105642014-03-20 16:08:34 +0000198
Renato Golin33f973a2014-04-01 09:51:49 +0000199.. productionlist::
200 SimpleValue: `TokIdentifier`
Renato Golinca105642014-03-20 16:08:34 +0000201
Renato Golin33f973a2014-04-01 09:51:49 +0000202The value will be the variable referenced by the identifier. It can be one
203of:
Renato Golinca105642014-03-20 16:08:34 +0000204
Renato Golin33f973a2014-04-01 09:51:49 +0000205.. The code for this is exceptionally abstruse. These examples are a
206 best-effort attempt.
Renato Golinca105642014-03-20 16:08:34 +0000207
Renato Golin33f973a2014-04-01 09:51:49 +0000208* name of a ``def``, such as the use of ``Bar`` in::
Renato Golinca105642014-03-20 16:08:34 +0000209
Renato Golin33f973a2014-04-01 09:51:49 +0000210 def Bar : SomeClass {
211 int X = 5;
212 }
Renato Golinca105642014-03-20 16:08:34 +0000213
Renato Golin33f973a2014-04-01 09:51:49 +0000214 def Foo {
215 SomeClass Baz = Bar;
216 }
Renato Golinca105642014-03-20 16:08:34 +0000217
Renato Golin33f973a2014-04-01 09:51:49 +0000218* value local to a ``def``, such as the use of ``Bar`` in::
Renato Golinca105642014-03-20 16:08:34 +0000219
Renato Golin33f973a2014-04-01 09:51:49 +0000220 def Foo {
221 int Bar = 5;
222 int Baz = Bar;
223 }
Renato Golinca105642014-03-20 16:08:34 +0000224
Renato Golin33f973a2014-04-01 09:51:49 +0000225* a template arg of a ``class``, such as the use of ``Bar`` in::
Renato Golinca105642014-03-20 16:08:34 +0000226
Renato Golin33f973a2014-04-01 09:51:49 +0000227 class Foo<int Bar> {
228 int Baz = Bar;
229 }
Renato Golinca105642014-03-20 16:08:34 +0000230
Renato Golin33f973a2014-04-01 09:51:49 +0000231* value local to a ``multiclass``, such as the use of ``Bar`` in::
Renato Golinca105642014-03-20 16:08:34 +0000232
Renato Golin33f973a2014-04-01 09:51:49 +0000233 multiclass Foo {
234 int Bar = 5;
235 int Baz = Bar;
236 }
Renato Golinca105642014-03-20 16:08:34 +0000237
Renato Golin33f973a2014-04-01 09:51:49 +0000238* a template arg to a ``multiclass``, such as the use of ``Bar`` in::
Renato Golinca105642014-03-20 16:08:34 +0000239
Renato Golin33f973a2014-04-01 09:51:49 +0000240 multiclass Foo<int Bar> {
241 int Baz = Bar;
242 }
Renato Golinca105642014-03-20 16:08:34 +0000243
Renato Golin33f973a2014-04-01 09:51:49 +0000244.. productionlist::
245 SimpleValue: `TokInteger`
Renato Golinca105642014-03-20 16:08:34 +0000246
Renato Golin33f973a2014-04-01 09:51:49 +0000247This represents the numeric value of the integer.
Renato Golinca105642014-03-20 16:08:34 +0000248
Renato Golin33f973a2014-04-01 09:51:49 +0000249.. productionlist::
250 SimpleValue: `TokString`+
Renato Golinca105642014-03-20 16:08:34 +0000251
Renato Golin33f973a2014-04-01 09:51:49 +0000252Multiple adjacent string literals are concatenated like in C/C++. The value
253is the concatenation of the strings.
Renato Golinca105642014-03-20 16:08:34 +0000254
Renato Golin33f973a2014-04-01 09:51:49 +0000255.. productionlist::
256 SimpleValue: `TokCodeFragment`
Renato Golinca105642014-03-20 16:08:34 +0000257
Renato Golin33f973a2014-04-01 09:51:49 +0000258The value is the string value of the code fragment.
Renato Golinca105642014-03-20 16:08:34 +0000259
Renato Golin33f973a2014-04-01 09:51:49 +0000260.. productionlist::
261 SimpleValue: "?"
Renato Golinca105642014-03-20 16:08:34 +0000262
Renato Golin33f973a2014-04-01 09:51:49 +0000263``?`` represents an "unset" initializer.
Sean Silva1b600182013-01-07 02:43:44 +0000264
Renato Golin33f973a2014-04-01 09:51:49 +0000265.. productionlist::
266 SimpleValue: "{" `ValueList` "}"
267 ValueList: [`ValueListNE`]
268 ValueListNE: `Value` ("," `Value`)*
Sean Silva1b600182013-01-07 02:43:44 +0000269
Renato Golin33f973a2014-04-01 09:51:49 +0000270This represents a sequence of bits, as would be used to initialize a
271``bits<n>`` field (where ``n`` is the number of bits).
Sean Silva1b600182013-01-07 02:43:44 +0000272
Renato Golin33f973a2014-04-01 09:51:49 +0000273.. productionlist::
274 SimpleValue: `ClassID` "<" `ValueListNE` ">"
Sean Silva1b600182013-01-07 02:43:44 +0000275
Renato Golin33f973a2014-04-01 09:51:49 +0000276This generates a new anonymous record definition (as would be created by an
277unnamed ``def`` inheriting from the given class with the given template
278arguments) and the value is the value of that record definition.
Sean Silva1b600182013-01-07 02:43:44 +0000279
Renato Golin33f973a2014-04-01 09:51:49 +0000280.. productionlist::
281 SimpleValue: "[" `ValueList` "]" ["<" `Type` ">"]
Sean Silva1b600182013-01-07 02:43:44 +0000282
Renato Golin33f973a2014-04-01 09:51:49 +0000283A list initializer. The optional :token:`Type` can be used to indicate a
284specific element type, otherwise the element type will be deduced from the
285given values.
Sean Silva1b600182013-01-07 02:43:44 +0000286
Renato Golin33f973a2014-04-01 09:51:49 +0000287.. The initial `DagArg` of the dag must start with an identifier or
288 !cast, but this is more of an implementation detail and so for now just
289 leave it out.
Sean Silva1b600182013-01-07 02:43:44 +0000290
Renato Golin33f973a2014-04-01 09:51:49 +0000291.. productionlist::
292 SimpleValue: "(" `DagArg` `DagArgList` ")"
293 DagArgList: `DagArg` ("," `DagArg`)*
294 DagArg: `Value` [":" `TokVarName`] | `TokVarName`
Sean Silva1b600182013-01-07 02:43:44 +0000295
Renato Golin33f973a2014-04-01 09:51:49 +0000296The initial :token:`DagArg` is called the "operator" of the dag.
Sean Silva1b600182013-01-07 02:43:44 +0000297
Renato Golin33f973a2014-04-01 09:51:49 +0000298.. productionlist::
299 SimpleValue: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")"
Sean Silva1b600182013-01-07 02:43:44 +0000300
Renato Golin33f973a2014-04-01 09:51:49 +0000301Bodies
302------
Sean Silva1b600182013-01-07 02:43:44 +0000303
Renato Golin33f973a2014-04-01 09:51:49 +0000304.. productionlist::
305 ObjectBody: `BaseClassList` `Body`
306 BaseClassList: [":" `BaseClassListNE`]
307 BaseClassListNE: `SubClassRef` ("," `SubClassRef`)*
308 SubClassRef: (`ClassID` | `MultiClassID`) ["<" `ValueList` ">"]
309 DefmID: `TokIdentifier`
Sean Silva1b600182013-01-07 02:43:44 +0000310
Renato Golin33f973a2014-04-01 09:51:49 +0000311The version with the :token:`MultiClassID` is only valid in the
312:token:`BaseClassList` of a ``defm``.
313The :token:`MultiClassID` should be the name of a ``multiclass``.
Sean Silva1b600182013-01-07 02:43:44 +0000314
Renato Golin33f973a2014-04-01 09:51:49 +0000315.. put this somewhere else
Sean Silva1b600182013-01-07 02:43:44 +0000316
Renato Golin33f973a2014-04-01 09:51:49 +0000317It is after parsing the base class list that the "let stack" is applied.
Sean Silva1b600182013-01-07 02:43:44 +0000318
Renato Golin33f973a2014-04-01 09:51:49 +0000319.. productionlist::
320 Body: ";" | "{" BodyList "}"
321 BodyList: BodyItem*
322 BodyItem: `Declaration` ";"
323 :| "let" `TokIdentifier` [`RangeList`] "=" `Value` ";"
Sean Silva1b600182013-01-07 02:43:44 +0000324
Renato Golin33f973a2014-04-01 09:51:49 +0000325The ``let`` form allows overriding the value of an inherited field.
Sean Silva1b600182013-01-07 02:43:44 +0000326
Renato Golin33f973a2014-04-01 09:51:49 +0000327``def``
328-------
Sean Silva1b600182013-01-07 02:43:44 +0000329
Renato Golin33f973a2014-04-01 09:51:49 +0000330.. TODO::
331 There can be pastes in the names here, like ``#NAME#``. Look into that
332 and document it (it boils down to ParseIDValue with IDParseMode ==
333 ParseNameMode). ParseObjectName calls into the general ParseValue, with
334 the only different from "arbitrary expression parsing" being IDParseMode
335 == Mode.
Sean Silva1b600182013-01-07 02:43:44 +0000336
Renato Golin33f973a2014-04-01 09:51:49 +0000337.. productionlist::
338 Def: "def" `TokIdentifier` `ObjectBody`
Sean Silva1b600182013-01-07 02:43:44 +0000339
Renato Golin33f973a2014-04-01 09:51:49 +0000340Defines a record whose name is given by the :token:`TokIdentifier`. The
341fields of the record are inherited from the base classes and defined in the
342body.
Sean Silva1b600182013-01-07 02:43:44 +0000343
Renato Golin33f973a2014-04-01 09:51:49 +0000344Special handling occurs if this ``def`` appears inside a ``multiclass`` or
345a ``foreach``.
Sean Silva1b600182013-01-07 02:43:44 +0000346
Renato Golin33f973a2014-04-01 09:51:49 +0000347``defm``
348--------
Sean Silva1b600182013-01-07 02:43:44 +0000349
Renato Golin33f973a2014-04-01 09:51:49 +0000350.. productionlist::
351 Defm: "defm" `TokIdentifier` ":" `BaseClassListNE` ";"
Sean Silva1b600182013-01-07 02:43:44 +0000352
Renato Golin33f973a2014-04-01 09:51:49 +0000353Note that in the :token:`BaseClassList`, all of the ``multiclass``'s must
354precede any ``class``'s that appear.
Sean Silva1b600182013-01-07 02:43:44 +0000355
Renato Golin33f973a2014-04-01 09:51:49 +0000356``foreach``
357-----------
Sean Silva1b600182013-01-07 02:43:44 +0000358
Renato Golin33f973a2014-04-01 09:51:49 +0000359.. productionlist::
360 Foreach: "foreach" `Declaration` "in" "{" `Object`* "}"
361 :| "foreach" `Declaration` "in" `Object`
Sean Silva1b600182013-01-07 02:43:44 +0000362
Renato Golin33f973a2014-04-01 09:51:49 +0000363The value assigned to the variable in the declaration is iterated over and
364the object or object list is reevaluated with the variable set at each
365iterated value.
Sean Silva1b600182013-01-07 02:43:44 +0000366
Renato Golin33f973a2014-04-01 09:51:49 +0000367Top-Level ``let``
368-----------------
Sean Silva1b600182013-01-07 02:43:44 +0000369
Renato Golin33f973a2014-04-01 09:51:49 +0000370.. productionlist::
371 Let: "let" `LetList` "in" "{" `Object`* "}"
372 :| "let" `LetList` "in" `Object`
373 LetList: `LetItem` ("," `LetItem`)*
374 LetItem: `TokIdentifier` [`RangeList`] "=" `Value`
Sean Silva1b600182013-01-07 02:43:44 +0000375
Renato Golin33f973a2014-04-01 09:51:49 +0000376This is effectively equivalent to ``let`` inside the body of a record
377except that it applies to multiple records at a time. The bindings are
378applied at the end of parsing the base classes of a record.
Sean Silva1b600182013-01-07 02:43:44 +0000379
Renato Golin33f973a2014-04-01 09:51:49 +0000380``multiclass``
381--------------
Sean Silva1b600182013-01-07 02:43:44 +0000382
Renato Golin33f973a2014-04-01 09:51:49 +0000383.. productionlist::
384 MultiClass: "multiclass" `TokIdentifier` [`TemplateArgList`]
385 : [":" `BaseMultiClassList`] "{" `MultiClassObject`+ "}"
386 BaseMultiClassList: `MultiClassID` ("," `MultiClassID`)*
387 MultiClassID: `TokIdentifier`
388 MultiClassObject: `Def` | `Defm` | `Let` | `Foreach`