| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 1 | //===-- FileParser.y - Parser for TableGen files ----------------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //  This file implements the bison parser for Table Generator files... | 
|  | 4 | // | 
| Chris Lattner | 44d2c35 | 2003-10-13 03:32:08 +0000 | [diff] [blame] | 5 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 6 |  | 
|  | 7 | %{ | 
|  | 8 | #include "Record.h" | 
|  | 9 | #include "Support/StringExtras.h" | 
|  | 10 | #include <algorithm> | 
|  | 11 | #include <cstdio> | 
|  | 12 | #define YYERROR_VERBOSE 1 | 
|  | 13 |  | 
|  | 14 | int yyerror(const char *ErrorMsg); | 
|  | 15 | int yylex(); | 
|  | 16 | extern int Filelineno; | 
|  | 17 | static Record *CurRec = 0; | 
|  | 18 |  | 
|  | 19 | typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy; | 
|  | 20 |  | 
|  | 21 | struct LetRecord { | 
|  | 22 | std::string Name; | 
|  | 23 | std::vector<unsigned> Bits; | 
|  | 24 | Init *Value; | 
|  | 25 | bool HasBits; | 
|  | 26 | LetRecord(const std::string &N, std::vector<unsigned> *B, Init *V) | 
|  | 27 | : Name(N), Value(V), HasBits(B != 0) { | 
|  | 28 | if (HasBits) Bits = *B; | 
|  | 29 | } | 
|  | 30 | }; | 
|  | 31 |  | 
|  | 32 | static std::vector<std::vector<LetRecord> > LetStack; | 
|  | 33 |  | 
|  | 34 |  | 
|  | 35 | extern std::ostream &err(); | 
|  | 36 |  | 
|  | 37 | static void addValue(const RecordVal &RV) { | 
|  | 38 | if (RecordVal *ERV = CurRec->getValue(RV.getName())) { | 
|  | 39 | // The value already exists in the class, treat this as a set... | 
|  | 40 | if (ERV->setValue(RV.getValue())) { | 
|  | 41 | err() << "New definition of '" << RV.getName() << "' of type '" | 
|  | 42 | << *RV.getType() << "' is incompatible with previous " | 
|  | 43 | << "definition of type '" << *ERV->getType() << "'!\n"; | 
|  | 44 | abort(); | 
|  | 45 | } | 
|  | 46 | } else { | 
|  | 47 | CurRec->addValue(RV); | 
|  | 48 | } | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | static void addSuperClass(Record *SC) { | 
|  | 52 | if (CurRec->isSubClassOf(SC)) { | 
|  | 53 | err() << "Already subclass of '" << SC->getName() << "'!\n"; | 
|  | 54 | abort(); | 
|  | 55 | } | 
|  | 56 | CurRec->addSuperClass(SC); | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | static void setValue(const std::string &ValName, | 
|  | 60 | std::vector<unsigned> *BitList, Init *V) { | 
|  | 61 | if (!V) return ; | 
|  | 62 |  | 
|  | 63 | RecordVal *RV = CurRec->getValue(ValName); | 
|  | 64 | if (RV == 0) { | 
|  | 65 | err() << "Value '" << ValName << "' unknown!\n"; | 
|  | 66 | abort(); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | // If we are assigning to a subset of the bits in the value... then we must be | 
|  | 70 | // assigning to a field of BitsRecTy, which must have a BitsInit | 
|  | 71 | // initializer... | 
|  | 72 | // | 
|  | 73 | if (BitList) { | 
|  | 74 | BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue()); | 
|  | 75 | if (CurVal == 0) { | 
|  | 76 | err() << "Value '" << ValName << "' is not a bits type!\n"; | 
|  | 77 | abort(); | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | // Convert the incoming value to a bits type of the appropriate size... | 
|  | 81 | Init *BI = V->convertInitializerTo(new BitsRecTy(BitList->size())); | 
|  | 82 | if (BI == 0) { | 
|  | 83 | V->convertInitializerTo(new BitsRecTy(BitList->size())); | 
|  | 84 | err() << "Initializer '" << *V << "' not compatible with bit range!\n"; | 
|  | 85 | abort(); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | // We should have a BitsInit type now... | 
|  | 89 | assert(dynamic_cast<BitsInit*>(BI) != 0 || &(std::cerr << *BI) == 0); | 
|  | 90 | BitsInit *BInit = (BitsInit*)BI; | 
|  | 91 |  | 
|  | 92 | BitsInit *NewVal = new BitsInit(CurVal->getNumBits()); | 
|  | 93 |  | 
|  | 94 | // Loop over bits, assigning values as appropriate... | 
|  | 95 | for (unsigned i = 0, e = BitList->size(); i != e; ++i) { | 
|  | 96 | unsigned Bit = (*BitList)[i]; | 
|  | 97 | if (NewVal->getBit(Bit)) { | 
|  | 98 | err() << "Cannot set bit #" << Bit << " of value '" << ValName | 
|  | 99 | << "' more than once!\n"; | 
|  | 100 | abort(); | 
|  | 101 | } | 
|  | 102 | NewVal->setBit(Bit, BInit->getBit(i)); | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) | 
|  | 106 | if (NewVal->getBit(i) == 0) | 
|  | 107 | NewVal->setBit(i, CurVal->getBit(i)); | 
|  | 108 |  | 
|  | 109 | V = NewVal; | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | if (RV->setValue(V)) { | 
|  | 113 | err() << "Value '" << ValName << "' of type '" << *RV->getType() | 
|  | 114 | << "' is incompatible with initializer '" << *V << "'!\n"; | 
|  | 115 | abort(); | 
|  | 116 | } | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) { | 
|  | 120 | // Add all of the values in the subclass into the current class... | 
|  | 121 | const std::vector<RecordVal> &Vals = SC->getValues(); | 
|  | 122 | for (unsigned i = 0, e = Vals.size(); i != e; ++i) | 
|  | 123 | addValue(Vals[i]); | 
|  | 124 |  | 
|  | 125 | const std::vector<std::string> &TArgs = SC->getTemplateArgs(); | 
|  | 126 |  | 
|  | 127 | // Ensure that an appropriate number of template arguments are specified... | 
|  | 128 | if (TArgs.size() < TemplateArgs.size()) { | 
|  | 129 | err() << "ERROR: More template args specified than expected!\n"; | 
|  | 130 | abort(); | 
|  | 131 | } else {    // This class expects template arguments... | 
|  | 132 | // Loop over all of the template arguments, setting them to the specified | 
|  | 133 | // value or leaving them as the default as necessary. | 
|  | 134 | for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { | 
|  | 135 | if (i < TemplateArgs.size()) {  // A value is specified for this temp-arg? | 
|  | 136 | // Set it now. | 
|  | 137 | setValue(TArgs[i], 0, TemplateArgs[i]); | 
|  | 138 | } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { | 
|  | 139 | err() << "ERROR: Value not specified for template argument #" | 
|  | 140 | << i << " (" << TArgs[i] << ") of subclass '" << SC->getName() | 
|  | 141 | << "'!\n"; | 
|  | 142 | abort(); | 
|  | 143 | } | 
|  | 144 | } | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 |  | 
|  | 148 | // Since everything went well, we can now set the "superclass" list for the | 
|  | 149 | // current record. | 
|  | 150 | const std::vector<Record*>   &SCs  = SC->getSuperClasses(); | 
|  | 151 | for (unsigned i = 0, e = SCs.size(); i != e; ++i) | 
|  | 152 | addSuperClass(SCs[i]); | 
|  | 153 | addSuperClass(SC); | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 |  | 
|  | 157 | %} | 
|  | 158 |  | 
|  | 159 | %union { | 
|  | 160 | std::string          *StrVal; | 
|  | 161 | int                   IntVal; | 
|  | 162 | RecTy                *Ty; | 
|  | 163 | Init                 *Initializer; | 
|  | 164 | std::vector<Init*>   *FieldList; | 
|  | 165 | std::vector<unsigned>*BitList; | 
|  | 166 | Record               *Rec; | 
|  | 167 | SubClassRefTy        *SubClassRef; | 
|  | 168 | std::vector<SubClassRefTy> *SubClassList; | 
|  | 169 | std::vector<std::pair<Init*, std::string> > *DagValueList; | 
|  | 170 | }; | 
|  | 171 |  | 
|  | 172 | %token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN | 
|  | 173 | %token <IntVal>      INTVAL | 
|  | 174 | %token <StrVal>      ID VARNAME STRVAL CODEFRAGMENT | 
|  | 175 |  | 
|  | 176 | %type <Ty>           Type | 
|  | 177 | %type <Rec>          ClassInst DefInst Object ObjectBody ClassID | 
|  | 178 |  | 
|  | 179 | %type <SubClassRef>  SubClassRef | 
|  | 180 | %type <SubClassList> ClassList ClassListNE | 
|  | 181 | %type <IntVal>       OptPrefix | 
|  | 182 | %type <Initializer>  Value OptValue | 
|  | 183 | %type <DagValueList> DagArgList DagArgListNE | 
|  | 184 | %type <FieldList>    ValueList ValueListNE | 
|  | 185 | %type <BitList>      BitList OptBitList RBitList | 
|  | 186 | %type <StrVal>       Declaration OptID OptVarName | 
|  | 187 |  | 
|  | 188 | %start File | 
|  | 189 | %% | 
|  | 190 |  | 
|  | 191 | ClassID : ID { | 
|  | 192 | $$ = Records.getClass(*$1); | 
|  | 193 | if ($$ == 0) { | 
|  | 194 | err() << "Couldn't find class '" << *$1 << "'!\n"; | 
|  | 195 | abort(); | 
|  | 196 | } | 
|  | 197 | delete $1; | 
|  | 198 | }; | 
|  | 199 |  | 
|  | 200 |  | 
|  | 201 | // TableGen types... | 
|  | 202 | Type : STRING {                       // string type | 
|  | 203 | $$ = new StringRecTy(); | 
|  | 204 | } | BIT {                           // bit type | 
|  | 205 | $$ = new BitRecTy(); | 
|  | 206 | } | BITS '<' INTVAL '>' {           // bits<x> type | 
|  | 207 | $$ = new BitsRecTy($3); | 
|  | 208 | } | INT {                           // int type | 
|  | 209 | $$ = new IntRecTy(); | 
|  | 210 | } | LIST '<' Type '>'    {          // list<x> type | 
|  | 211 | $$ = new ListRecTy($3); | 
|  | 212 | } | CODE {                          // code type | 
|  | 213 | $$ = new CodeRecTy(); | 
|  | 214 | } | DAG {                           // dag type | 
|  | 215 | $$ = new DagRecTy(); | 
|  | 216 | } | ClassID {                       // Record Type | 
|  | 217 | $$ = new RecordRecTy($1); | 
|  | 218 | }; | 
|  | 219 |  | 
|  | 220 | OptPrefix : /*empty*/ { $$ = 0; } | FIELD { $$ = 1; }; | 
|  | 221 |  | 
|  | 222 | OptValue : /*empty*/ { $$ = 0; } | '=' Value { $$ = $2; }; | 
|  | 223 |  | 
|  | 224 | Value : INTVAL { | 
|  | 225 | $$ = new IntInit($1); | 
|  | 226 | } | STRVAL { | 
|  | 227 | $$ = new StringInit(*$1); | 
|  | 228 | delete $1; | 
|  | 229 | } | CODEFRAGMENT { | 
|  | 230 | $$ = new CodeInit(*$1); | 
|  | 231 | delete $1; | 
|  | 232 | } | '?' { | 
|  | 233 | $$ = new UnsetInit(); | 
|  | 234 | } | '{' ValueList '}' { | 
|  | 235 | BitsInit *Init = new BitsInit($2->size()); | 
|  | 236 | for (unsigned i = 0, e = $2->size(); i != e; ++i) { | 
|  | 237 | struct Init *Bit = (*$2)[i]->convertInitializerTo(new BitRecTy()); | 
|  | 238 | if (Bit == 0) { | 
|  | 239 | err() << "Element #" << i << " (" << *(*$2)[i] | 
|  | 240 | << ") is not convertable to a bit!\n"; | 
|  | 241 | abort(); | 
|  | 242 | } | 
|  | 243 | Init->setBit($2->size()-i-1, Bit); | 
|  | 244 | } | 
|  | 245 | $$ = Init; | 
|  | 246 | delete $2; | 
|  | 247 | } | ID { | 
|  | 248 | if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { | 
|  | 249 | $$ = new VarInit(*$1, RV->getType()); | 
|  | 250 | } else if (Record *D = Records.getDef(*$1)) { | 
|  | 251 | $$ = new DefInit(D); | 
|  | 252 | } else { | 
|  | 253 | err() << "Variable not defined: '" << *$1 << "'!\n"; | 
|  | 254 | abort(); | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | delete $1; | 
|  | 258 | } | Value '{' BitList '}' { | 
|  | 259 | $$ = $1->convertInitializerBitRange(*$3); | 
|  | 260 | if ($$ == 0) { | 
|  | 261 | err() << "Invalid bit range for value '" << *$1 << "'!\n"; | 
|  | 262 | abort(); | 
|  | 263 | } | 
|  | 264 | delete $3; | 
|  | 265 | } | '[' ValueList ']' { | 
|  | 266 | $$ = new ListInit(*$2); | 
|  | 267 | delete $2; | 
|  | 268 | } | Value '.' ID { | 
|  | 269 | if (!$1->getFieldType(*$3)) { | 
|  | 270 | err() << "Cannot access field '" << *$3 << "' of value '" << *$1 << "!\n"; | 
|  | 271 | abort(); | 
|  | 272 | } | 
|  | 273 | $$ = new FieldInit($1, *$3); | 
|  | 274 | delete $3; | 
|  | 275 | } | '(' ID DagArgList ')' { | 
|  | 276 | Record *D = Records.getDef(*$2); | 
|  | 277 | if (D == 0) { | 
|  | 278 | err() << "Invalid def '" << *$2 << "'!\n"; | 
|  | 279 | abort(); | 
|  | 280 | } | 
|  | 281 | $$ = new DagInit(D, *$3); | 
|  | 282 | delete $2; delete $3; | 
|  | 283 | }; | 
|  | 284 |  | 
|  | 285 | OptVarName : /* empty */ { | 
|  | 286 | $$ = new std::string(); | 
|  | 287 | } | 
|  | 288 | | ':' VARNAME { | 
|  | 289 | $$ = $2; | 
|  | 290 | }; | 
|  | 291 |  | 
|  | 292 | DagArgListNE : Value OptVarName { | 
|  | 293 | $$ = new std::vector<std::pair<Init*, std::string> >(); | 
|  | 294 | $$->push_back(std::make_pair($1, *$2)); | 
|  | 295 | delete $2; | 
|  | 296 | } | 
|  | 297 | | DagArgListNE ',' Value OptVarName { | 
|  | 298 | $1->push_back(std::make_pair($3, *$4)); | 
|  | 299 | delete $4; | 
|  | 300 | $$ = $1; | 
|  | 301 | }; | 
|  | 302 |  | 
|  | 303 | DagArgList : /*empty*/ { | 
|  | 304 | $$ = new std::vector<std::pair<Init*, std::string> >(); | 
|  | 305 | } | 
|  | 306 | | DagArgListNE { $$ = $1; }; | 
|  | 307 |  | 
|  | 308 |  | 
|  | 309 | RBitList : INTVAL { | 
|  | 310 | $$ = new std::vector<unsigned>(); | 
|  | 311 | $$->push_back($1); | 
|  | 312 | } | INTVAL '-' INTVAL { | 
|  | 313 | if ($1 < $3 || $1 < 0 || $3 < 0) { | 
|  | 314 | err() << "Invalid bit range: " << $1 << "-" << $3 << "!\n"; | 
|  | 315 | abort(); | 
|  | 316 | } | 
|  | 317 | $$ = new std::vector<unsigned>(); | 
|  | 318 | for (int i = $1; i >= $3; --i) | 
|  | 319 | $$->push_back(i); | 
|  | 320 | } | INTVAL INTVAL { | 
|  | 321 | $2 = -$2; | 
|  | 322 | if ($1 < $2 || $1 < 0 || $2 < 0) { | 
|  | 323 | err() << "Invalid bit range: " << $1 << "-" << $2 << "!\n"; | 
|  | 324 | abort(); | 
|  | 325 | } | 
|  | 326 | $$ = new std::vector<unsigned>(); | 
|  | 327 | for (int i = $1; i >= $2; --i) | 
|  | 328 | $$->push_back(i); | 
|  | 329 | } | RBitList ',' INTVAL { | 
|  | 330 | ($$=$1)->push_back($3); | 
|  | 331 | } | RBitList ',' INTVAL '-' INTVAL { | 
|  | 332 | if ($3 < $5 || $3 < 0 || $5 < 0) { | 
|  | 333 | err() << "Invalid bit range: " << $3 << "-" << $5 << "!\n"; | 
|  | 334 | abort(); | 
|  | 335 | } | 
|  | 336 | $$ = $1; | 
|  | 337 | for (int i = $3; i >= $5; --i) | 
|  | 338 | $$->push_back(i); | 
|  | 339 | } | RBitList ',' INTVAL INTVAL { | 
|  | 340 | $4 = -$4; | 
|  | 341 | if ($3 < $4 || $3 < 0 || $4 < 0) { | 
|  | 342 | err() << "Invalid bit range: " << $3 << "-" << $4 << "!\n"; | 
|  | 343 | abort(); | 
|  | 344 | } | 
|  | 345 | $$ = $1; | 
|  | 346 | for (int i = $3; i >= $4; --i) | 
|  | 347 | $$->push_back(i); | 
|  | 348 | }; | 
|  | 349 |  | 
|  | 350 | BitList : RBitList { $$ = $1; std::reverse($1->begin(), $1->end()); }; | 
|  | 351 |  | 
|  | 352 | OptBitList : /*empty*/ { $$ = 0; } | '{' BitList '}' { $$ = $2; }; | 
|  | 353 |  | 
|  | 354 |  | 
|  | 355 |  | 
|  | 356 | ValueList : /*empty*/ { | 
|  | 357 | $$ = new std::vector<Init*>(); | 
|  | 358 | } | ValueListNE { | 
|  | 359 | $$ = $1; | 
|  | 360 | }; | 
|  | 361 |  | 
|  | 362 | ValueListNE : Value { | 
|  | 363 | $$ = new std::vector<Init*>(); | 
|  | 364 | $$->push_back($1); | 
|  | 365 | } | ValueListNE ',' Value { | 
|  | 366 | ($$ = $1)->push_back($3); | 
|  | 367 | }; | 
|  | 368 |  | 
|  | 369 | Declaration : OptPrefix Type ID OptValue { | 
|  | 370 | addValue(RecordVal(*$3, $2, $1)); | 
|  | 371 | setValue(*$3, 0, $4); | 
|  | 372 | $$ = $3; | 
|  | 373 | }; | 
|  | 374 |  | 
|  | 375 | BodyItem : Declaration ';' { | 
|  | 376 | delete $1; | 
|  | 377 | } | LET ID OptBitList '=' Value ';' { | 
|  | 378 | setValue(*$2, $3, $5); | 
|  | 379 | delete $2; | 
|  | 380 | delete $3; | 
|  | 381 | }; | 
|  | 382 |  | 
|  | 383 | BodyList : /*empty*/ | BodyList BodyItem; | 
|  | 384 | Body : ';' | '{' BodyList '}'; | 
|  | 385 |  | 
|  | 386 | SubClassRef : ClassID { | 
|  | 387 | $$ = new SubClassRefTy($1, new std::vector<Init*>()); | 
|  | 388 | } | ClassID '<' ValueListNE '>' { | 
|  | 389 | $$ = new SubClassRefTy($1, $3); | 
|  | 390 | }; | 
|  | 391 |  | 
|  | 392 | ClassListNE : SubClassRef { | 
|  | 393 | $$ = new std::vector<SubClassRefTy>(); | 
|  | 394 | $$->push_back(*$1); | 
|  | 395 | delete $1; | 
|  | 396 | } | 
|  | 397 | | ClassListNE ',' SubClassRef { | 
|  | 398 | ($$=$1)->push_back(*$3); | 
|  | 399 | delete $3; | 
|  | 400 | }; | 
|  | 401 |  | 
|  | 402 | ClassList : /*empty */ { | 
|  | 403 | $$ = new std::vector<SubClassRefTy>(); | 
|  | 404 | } | 
|  | 405 | | ':' ClassListNE { | 
|  | 406 | $$ = $2; | 
|  | 407 | }; | 
|  | 408 |  | 
|  | 409 | DeclListNE : Declaration { | 
|  | 410 | CurRec->addTemplateArg(*$1); | 
|  | 411 | delete $1; | 
|  | 412 | } | DeclListNE ',' Declaration { | 
|  | 413 | CurRec->addTemplateArg(*$3); | 
|  | 414 | delete $3; | 
|  | 415 | }; | 
|  | 416 |  | 
|  | 417 | TemplateArgList : '<' DeclListNE '>' {}; | 
|  | 418 | OptTemplateArgList : /*empty*/ | TemplateArgList; | 
|  | 419 |  | 
|  | 420 | OptID : ID { $$ = $1; } | /*empty*/ { $$ = new std::string(); }; | 
|  | 421 |  | 
|  | 422 | ObjectBody : OptID { | 
|  | 423 | static unsigned AnonCounter = 0; | 
|  | 424 | if ($1->empty()) | 
|  | 425 | *$1 = "anonymous."+utostr(AnonCounter++); | 
|  | 426 | CurRec = new Record(*$1); | 
|  | 427 | delete $1; | 
|  | 428 | } OptTemplateArgList ClassList { | 
|  | 429 | for (unsigned i = 0, e = $4->size(); i != e; ++i) { | 
|  | 430 | addSubClass((*$4)[i].first, *(*$4)[i].second); | 
|  | 431 | // Delete the template arg values for the class | 
|  | 432 | delete (*$4)[i].second; | 
|  | 433 | } | 
|  | 434 |  | 
|  | 435 | // Process any variables on the set stack... | 
|  | 436 | for (unsigned i = 0, e = LetStack.size(); i != e; ++i) | 
|  | 437 | for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) | 
|  | 438 | setValue(LetStack[i][j].Name, | 
|  | 439 | LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0, | 
|  | 440 | LetStack[i][j].Value); | 
|  | 441 | } Body { | 
|  | 442 | CurRec->resolveReferences(); | 
|  | 443 |  | 
|  | 444 | // Now that all of the references have been resolved, we can delete template | 
|  | 445 | // arguments for superclasses, so they don't pollute our record, and so that | 
|  | 446 | // their names won't conflict with later uses of the name... | 
|  | 447 | for (unsigned i = 0, e = $4->size(); i != e; ++i) { | 
|  | 448 | Record *SuperClass = (*$4)[i].first; | 
|  | 449 | for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i) | 
|  | 450 | CurRec->removeValue(SuperClass->getTemplateArgs()[i]); | 
|  | 451 | } | 
|  | 452 | delete $4;   // Delete the class list... | 
|  | 453 |  | 
|  | 454 | $$ = CurRec; | 
|  | 455 | CurRec = 0; | 
|  | 456 | }; | 
|  | 457 |  | 
|  | 458 | ClassInst : CLASS ObjectBody { | 
|  | 459 | if (Records.getClass($2->getName())) { | 
|  | 460 | err() << "Class '" << $2->getName() << "' already defined!\n"; | 
|  | 461 | abort(); | 
|  | 462 | } | 
|  | 463 | Records.addClass($$ = $2); | 
|  | 464 | }; | 
|  | 465 |  | 
|  | 466 | DefInst : DEF ObjectBody { | 
|  | 467 | if (!$2->getTemplateArgs().empty()) { | 
|  | 468 | err() << "Def '" << $2->getName() | 
|  | 469 | << "' is not permitted to have template arguments!\n"; | 
|  | 470 | abort(); | 
|  | 471 | } | 
|  | 472 | // If ObjectBody has template arguments, it's an error. | 
|  | 473 | if (Records.getDef($2->getName())) { | 
|  | 474 | err() << "Def '" << $2->getName() << "' already defined!\n"; | 
|  | 475 | abort(); | 
|  | 476 | } | 
|  | 477 | Records.addDef($$ = $2); | 
|  | 478 | }; | 
|  | 479 |  | 
|  | 480 |  | 
|  | 481 | Object : ClassInst | DefInst; | 
|  | 482 |  | 
|  | 483 | LETItem : ID OptBitList '=' Value { | 
|  | 484 | LetStack.back().push_back(LetRecord(*$1, $2, $4)); | 
|  | 485 | delete $1; delete $2; | 
|  | 486 | }; | 
|  | 487 |  | 
|  | 488 | LETList : LETItem | LETList ',' LETItem; | 
|  | 489 |  | 
|  | 490 | // LETCommand - A 'LET' statement start... | 
|  | 491 | LETCommand : LET { LetStack.push_back(std::vector<LetRecord>()); } LETList IN; | 
|  | 492 |  | 
|  | 493 | // Support Set commands wrapping objects... both with and without braces. | 
|  | 494 | Object : LETCommand '{' ObjectList '}' { | 
|  | 495 | LetStack.pop_back(); | 
|  | 496 | } | 
|  | 497 | | LETCommand Object { | 
|  | 498 | LetStack.pop_back(); | 
|  | 499 | }; | 
|  | 500 |  | 
|  | 501 | ObjectList : Object {} | ObjectList Object {}; | 
|  | 502 |  | 
|  | 503 | File : ObjectList {}; | 
|  | 504 |  | 
|  | 505 | %% | 
|  | 506 |  | 
|  | 507 | int yyerror(const char *ErrorMsg) { | 
|  | 508 | err() << "Error parsing: " << ErrorMsg << "\n"; | 
|  | 509 | abort(); | 
|  | 510 | } |