1/* 2 * Copyright 2001-2007 Adrian Thurston <thurston@complang.org> 3 */ 4 5/* This file is part of Ragel. 6 * 7 * Ragel is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * Ragel is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Ragel; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#include "rlparse.h" 23#include "ragel.h" 24#include <iostream> 25#include <errno.h> 26#include <stdlib.h> 27 28using std::cout; 29using std::cerr; 30using std::endl; 31 32%%{ 33 34parser Parser; 35 36include "rlparse.kh"; 37 38start: section_list; 39 40section_list: section_list statement_list TK_EndSection; 41section_list: ; 42 43statement_list: statement_list statement; 44statement_list: ; 45 46statement: assignment commit; 47statement: instantiation commit; 48statement: action_spec commit; 49statement: alphtype_spec commit; 50statement: range_spec commit; 51statement: getkey_spec commit; 52statement: access_spec commit; 53statement: variable_spec commit; 54statement: export_block commit; 55statement: pre_push_spec commit; 56statement: post_pop_spec commit; 57statement: length_spec commit; 58 59length_spec: 60 KW_Length TK_Word ';' 61 final { 62 LengthDef *lengthDef = new LengthDef( $2->data ); 63 pd->lengthDefList.append( lengthDef ); 64 65 /* Generic creation of machine for instantiation and assignment. */ 66 MachineDef *machineDef = new MachineDef( lengthDef ); 67 tryMachineDef( $2->loc, $2->data, machineDef, false ); 68 }; 69 70pre_push_spec: 71 KW_PrePush '{' inline_block '}' 72 final { 73 if ( pd->prePushExpr != 0 ) { 74 /* Recover by just ignoring the duplicate. */ 75 error($2->loc) << "pre_push code already defined" << endl; 76 } 77 78 pd->prePushExpr = $3->inlineList; 79 }; 80 81 82post_pop_spec: 83 KW_PostPop '{' inline_block '}' 84 final { 85 if ( pd->postPopExpr != 0 ) { 86 /* Recover by just ignoring the duplicate. */ 87 error($2->loc) << "post_pop code already defined" << endl; 88 } 89 90 pd->postPopExpr = $3->inlineList; 91 }; 92 93 94export_open: KW_Export 95 final { 96 exportContext.append( true ); 97 }; 98 99nonterm opt_export 100{ 101 bool isSet; 102}; 103 104opt_export: export_open final { $$->isSet = true; }; 105opt_export: final { $$->isSet = false; }; 106 107export_block: export_open '{' statement_list '}' 108 final { 109 exportContext.remove( exportContext.length()-1 ); 110 }; 111 112assignment: 113 opt_export machine_name '=' join ';' final { 114 /* Main machine must be an instance. */ 115 bool isInstance = false; 116 if ( strcmp($2->token.data, mainMachine) == 0 ) { 117 warning($2->token.loc) << 118 "main machine will be implicitly instantiated" << endl; 119 isInstance = true; 120 } 121 122 /* Generic creation of machine for instantiation and assignment. */ 123 MachineDef *machineDef = new MachineDef( $4->join ); 124 tryMachineDef( $2->token.loc, $2->token.data, machineDef, isInstance ); 125 126 if ( $1->isSet ) 127 exportContext.remove( exportContext.length()-1 ); 128 129 $4->join->loc = $3->loc; 130 }; 131 132instantiation: 133 opt_export machine_name TK_ColonEquals join_or_lm ';' final { 134 /* Generic creation of machine for instantiation and assignment. */ 135 tryMachineDef( $2->token.loc, $2->token.data, $4->machineDef, true ); 136 137 if ( $1->isSet ) 138 exportContext.remove( exportContext.length()-1 ); 139 140 /* Pass a location to join_or_lm */ 141 if ( $4->machineDef->join != 0 ) 142 $4->machineDef->join->loc = $3->loc; 143 }; 144 145type token_type 146{ 147 Token token; 148}; 149 150nonterm machine_name uses token_type; 151 152machine_name: 153 TK_Word final { 154 /* Make/get the priority key. The name may have already been referenced 155 * and therefore exist. */ 156 PriorDictEl *priorDictEl; 157 if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) ) 158 pd->nextPriorKey += 1; 159 pd->curDefPriorKey = priorDictEl->value; 160 161 /* Make/get the local error key. */ 162 LocalErrDictEl *localErrDictEl; 163 if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) ) 164 pd->nextLocalErrKey += 1; 165 pd->curDefLocalErrKey = localErrDictEl->value; 166 167 $$->token = *$1; 168 }; 169 170action_spec: 171 KW_Action TK_Word '{' inline_block '}' final { 172 if ( pd->actionDict.find( $2->data ) ) { 173 /* Recover by just ignoring the duplicate. */ 174 error($2->loc) << "action \"" << $2->data << "\" already defined" << endl; 175 } 176 else { 177 //cerr << "NEW ACTION " << $2->data << " " << $4->inlineList << endl; 178 /* Add the action to the list of actions. */ 179 Action *newAction = new Action( $3->loc, $2->data, 180 $4->inlineList, pd->nextCondId++ ); 181 182 /* Insert to list and dict. */ 183 pd->actionList.append( newAction ); 184 pd->actionDict.insert( newAction ); 185 } 186 }; 187 188# Specifies the data type of the input alphabet. One or two words followed by a 189# semi-colon. 190alphtype_spec: 191 KW_AlphType TK_Word TK_Word ';' final { 192 if ( ! pd->setAlphType( $1->loc, $2->data, $3->data ) ) { 193 // Recover by ignoring the alphtype statement. 194 error($2->loc) << "\"" << $2->data << 195 " " << $3->data << "\" is not a valid alphabet type" << endl; 196 } 197 }; 198 199alphtype_spec: 200 KW_AlphType TK_Word ';' final { 201 if ( ! pd->setAlphType( $1->loc, $2->data ) ) { 202 // Recover by ignoring the alphtype statement. 203 error($2->loc) << "\"" << $2->data << 204 "\" is not a valid alphabet type" << endl; 205 } 206 }; 207 208# Specifies a range to assume that the input characters will fall into. 209range_spec: 210 KW_Range alphabet_num alphabet_num ';' final { 211 // Save the upper and lower ends of the range and emit the line number. 212 pd->lowerNum = $2->token.data; 213 pd->upperNum = $3->token.data; 214 pd->rangeLowLoc = $2->token.loc; 215 pd->rangeHighLoc = $3->token.loc; 216 }; 217 218getkey_spec: 219 KW_GetKey inline_expr ';' final { 220 pd->getKeyExpr = $2->inlineList; 221 }; 222 223access_spec: 224 KW_Access inline_expr ';' final { 225 pd->accessExpr = $2->inlineList; 226 }; 227 228variable_spec: 229 KW_Variable opt_whitespace TK_Word inline_expr ';' final { 230 /* FIXME: Need to implement the rest of this. */ 231 bool wasSet = pd->setVariable( $3->data, $4->inlineList ); 232 if ( !wasSet ) 233 error($3->loc) << "bad variable name" << endl; 234 }; 235 236opt_whitespace: opt_whitespace IL_WhiteSpace; 237opt_whitespace: ; 238 239# 240# Expressions 241# 242 243nonterm join_or_lm 244{ 245 MachineDef *machineDef; 246}; 247 248join_or_lm: 249 join final { 250 $$->machineDef = new MachineDef( $1->join ); 251 }; 252join_or_lm: 253 TK_BarStar lm_part_list '*' '|' final { 254 /* Create a new factor going to a longest match structure. Record 255 * in the parse data that we have a longest match. */ 256 LongestMatch *lm = new LongestMatch( $1->loc, $2->lmPartList ); 257 pd->lmList.append( lm ); 258 for ( LmPartList::Iter lmp = *($2->lmPartList); lmp.lte(); lmp++ ) 259 lmp->longestMatch = lm; 260 $$->machineDef = new MachineDef( lm ); 261 }; 262 263nonterm lm_part_list 264{ 265 LmPartList *lmPartList; 266}; 267 268lm_part_list: 269 lm_part_list longest_match_part 270 final { 271 if ( $2->lmPart != 0 ) 272 $1->lmPartList->append( $2->lmPart ); 273 $$->lmPartList = $1->lmPartList; 274 }; 275lm_part_list: 276 longest_match_part 277 final { 278 /* Create a new list with the part. */ 279 $$->lmPartList = new LmPartList; 280 if ( $1->lmPart != 0 ) 281 $$->lmPartList->append( $1->lmPart ); 282 }; 283 284nonterm longest_match_part 285{ 286 LongestMatchPart *lmPart; 287}; 288 289longest_match_part: 290 action_spec final { $$->lmPart = 0; }; 291longest_match_part: 292 assignment final { $$->lmPart = 0; }; 293longest_match_part: 294 join opt_lm_part_action ';' final { 295 $$->lmPart = 0; 296 Action *action = $2->action; 297 if ( action != 0 ) 298 action->isLmAction = true; 299 $$->lmPart = new LongestMatchPart( $1->join, action, 300 $3->loc, pd->nextLongestMatchId++ ); 301 302 /* Provide a location to join. Unfortunately We don't 303 * have the start of the join as in other occurances. Use the end. */ 304 $1->join->loc = $3->loc; 305 }; 306 307nonterm opt_lm_part_action 308{ 309 Action *action; 310}; 311 312opt_lm_part_action: 313 TK_DoubleArrow action_embed final { 314 $$->action = $2->action; 315 }; 316opt_lm_part_action: 317 action_embed_block final { 318 $$->action = $1->action; 319 }; 320opt_lm_part_action: 321 final { 322 $$->action = 0; 323 }; 324 325 326nonterm join 327{ 328 Join *join; 329}; 330 331join: 332 join ',' expression final { 333 /* Append the expression to the list and return it. */ 334 $1->join->exprList.append( $3->expression ); 335 $$->join = $1->join; 336 }; 337join: 338 expression final { 339 $$->join = new Join( $1->expression ); 340 }; 341 342nonterm expression 343{ 344 Expression *expression; 345}; 346 347expression: 348 expression '|' term_short final { 349 $$->expression = new Expression( $1->expression, 350 $3->term, Expression::OrType ); 351 }; 352expression: 353 expression '&' term_short final { 354 $$->expression = new Expression( $1->expression, 355 $3->term, Expression::IntersectType ); 356 }; 357expression: 358 expression '-' term_short final { 359 $$->expression = new Expression( $1->expression, 360 $3->term, Expression::SubtractType ); 361 }; 362expression: 363 expression TK_DashDash term_short final { 364 $$->expression = new Expression( $1->expression, 365 $3->term, Expression::StrongSubtractType ); 366 }; 367expression: 368 term_short final { 369 $$->expression = new Expression( $1->term ); 370 }; 371 372# This is where we resolve the ambiguity involving -. By default ragel tries to 373# do a longest match, which gives precedence to a concatenation because it is 374# innermost. What we need is to force term into a shortest match so that when - 375# is seen it doesn't try to extend term with a concatenation, but ends term and 376# goes for a subtraction. 377# 378# The shortest tag overrides the default longest match action ordering strategy 379# and instead forces a shortest match stragegy. The wrap the term production in 380# a new nonterminal 'term_short' to guarantee the shortest match behaviour. 381 382shortest term_short; 383nonterm term_short 384{ 385 Term *term; 386}; 387 388term_short: 389 term final { 390 $$->term = $1->term; 391 }; 392 393nonterm term 394{ 395 Term *term; 396}; 397 398term: 399 term factor_with_label final { 400 $$->term = new Term( $1->term, $2->factorWithAug ); 401 }; 402term: 403 term '.' factor_with_label final { 404 $$->term = new Term( $1->term, $3->factorWithAug ); 405 }; 406term: 407 term TK_ColonGt factor_with_label final { 408 $$->term = new Term( $1->term, $3->factorWithAug, Term::RightStartType ); 409 }; 410term: 411 term TK_ColonGtGt factor_with_label final { 412 $$->term = new Term( $1->term, $3->factorWithAug, Term::RightFinishType ); 413 }; 414term: 415 term TK_LtColon factor_with_label final { 416 $$->term = new Term( $1->term, 417 $3->factorWithAug, Term::LeftType ); 418 }; 419term: 420 factor_with_label final { 421 $$->term = new Term( $1->factorWithAug ); 422 }; 423 424nonterm factor_with_label 425{ 426 FactorWithAug *factorWithAug; 427}; 428 429factor_with_label: 430 TK_Word ':' factor_with_label final { 431 /* Add the label to the list and pass the factor up. */ 432 $3->factorWithAug->labels.prepend( Label($1->loc, $1->data) ); 433 $$->factorWithAug = $3->factorWithAug; 434 }; 435factor_with_label: 436 factor_with_ep final { 437 $$->factorWithAug = $1->factorWithAug; 438 }; 439 440nonterm factor_with_ep 441{ 442 FactorWithAug *factorWithAug; 443}; 444 445factor_with_ep: 446 factor_with_ep TK_Arrow local_state_ref final { 447 /* Add the target to the list and return the factor object. */ 448 $1->factorWithAug->epsilonLinks.append( EpsilonLink( $2->loc, nameRef ) ); 449 $$->factorWithAug = $1->factorWithAug; 450 }; 451factor_with_ep: 452 factor_with_aug final { 453 $$->factorWithAug = $1->factorWithAug; 454 }; 455 456nonterm factor_with_aug 457{ 458 FactorWithAug *factorWithAug; 459}; 460 461factor_with_aug: 462 factor_with_aug aug_type_base action_embed final { 463 /* Append the action to the factorWithAug, record the refernce from 464 * factorWithAug to the action and pass up the factorWithAug. */ 465 $1->factorWithAug->actions.append( 466 ParserAction( $2->loc, $2->augType, 0, $3->action ) ); 467 $$->factorWithAug = $1->factorWithAug; 468 }; 469factor_with_aug: 470 factor_with_aug aug_type_base priority_aug final { 471 /* Append the named priority to the factorWithAug and pass it up. */ 472 $1->factorWithAug->priorityAugs.append( 473 PriorityAug( $2->augType, pd->curDefPriorKey, $3->priorityNum ) ); 474 $$->factorWithAug = $1->factorWithAug; 475 }; 476factor_with_aug: 477 factor_with_aug aug_type_base '(' priority_name ',' priority_aug ')' final { 478 /* Append the priority using a default name. */ 479 $1->factorWithAug->priorityAugs.append( 480 PriorityAug( $2->augType, $4->priorityName, $6->priorityNum ) ); 481 $$->factorWithAug = $1->factorWithAug; 482 }; 483factor_with_aug: 484 factor_with_aug aug_type_cond action_embed final { 485 $1->factorWithAug->conditions.append( ConditionTest( $2->loc, 486 $2->augType, $3->action, true ) ); 487 $$->factorWithAug = $1->factorWithAug; 488 }; 489factor_with_aug: 490 factor_with_aug aug_type_cond '!' action_embed final { 491 $1->factorWithAug->conditions.append( ConditionTest( $2->loc, 492 $2->augType, $4->action, false ) ); 493 $$->factorWithAug = $1->factorWithAug; 494 }; 495factor_with_aug: 496 factor_with_aug aug_type_to_state action_embed final { 497 /* Append the action, pass it up. */ 498 $1->factorWithAug->actions.append( ParserAction( $2->loc, 499 $2->augType, 0, $3->action ) ); 500 $$->factorWithAug = $1->factorWithAug; 501 }; 502factor_with_aug: 503 factor_with_aug aug_type_from_state action_embed final { 504 /* Append the action, pass it up. */ 505 $1->factorWithAug->actions.append( ParserAction( $2->loc, 506 $2->augType, 0, $3->action ) ); 507 $$->factorWithAug = $1->factorWithAug; 508 }; 509factor_with_aug: 510 factor_with_aug aug_type_eof action_embed final { 511 /* Append the action, pass it up. */ 512 $1->factorWithAug->actions.append( ParserAction( $2->loc, 513 $2->augType, 0, $3->action ) ); 514 $$->factorWithAug = $1->factorWithAug; 515 }; 516factor_with_aug: 517 factor_with_aug aug_type_gbl_error action_embed final { 518 /* Append the action to the factorWithAug, record the refernce from 519 * factorWithAug to the action and pass up the factorWithAug. */ 520 $1->factorWithAug->actions.append( ParserAction( $2->loc, 521 $2->augType, pd->curDefLocalErrKey, $3->action ) ); 522 $$->factorWithAug = $1->factorWithAug; 523 }; 524factor_with_aug: 525 factor_with_aug aug_type_local_error action_embed final { 526 /* Append the action to the factorWithAug, record the refernce from 527 * factorWithAug to the action and pass up the factorWithAug. */ 528 $1->factorWithAug->actions.append( ParserAction( $2->loc, 529 $2->augType, pd->curDefLocalErrKey, $3->action ) ); 530 $$->factorWithAug = $1->factorWithAug; 531 }; 532factor_with_aug: 533 factor_with_aug aug_type_local_error '(' local_err_name ',' action_embed ')' final { 534 /* Append the action to the factorWithAug, record the refernce from 535 * factorWithAug to the action and pass up the factorWithAug. */ 536 $1->factorWithAug->actions.append( ParserAction( $2->loc, 537 $2->augType, $4->error_name, $6->action ) ); 538 $$->factorWithAug = $1->factorWithAug; 539 }; 540factor_with_aug: 541 factor_with_rep final { 542 $$->factorWithAug = new FactorWithAug( $1->factorWithRep ); 543 }; 544 545type aug_type 546{ 547 InputLoc loc; 548 AugType augType; 549}; 550 551# Classes of transtions on which to embed actions or change priorities. 552nonterm aug_type_base uses aug_type; 553 554aug_type_base: '@' final { $$->loc = $1->loc; $$->augType = at_finish; }; 555aug_type_base: '%' final { $$->loc = $1->loc; $$->augType = at_leave; }; 556aug_type_base: '$' final { $$->loc = $1->loc; $$->augType = at_all; }; 557aug_type_base: '>' final { $$->loc = $1->loc; $$->augType = at_start; }; 558 559# Embedding conditions. 560nonterm aug_type_cond uses aug_type; 561 562aug_type_cond: TK_StartCond final { $$->loc = $1->loc; $$->augType = at_start; }; 563aug_type_cond: '>' KW_When final { $$->loc = $1->loc; $$->augType = at_start; }; 564aug_type_cond: TK_AllCond final { $$->loc = $1->loc; $$->augType = at_all; }; 565aug_type_cond: '$' KW_When final { $$->loc = $1->loc; $$->augType = at_all; }; 566aug_type_cond: TK_LeavingCond final { $$->loc = $1->loc; $$->augType = at_leave; }; 567aug_type_cond: '%' KW_When final { $$->loc = $1->loc; $$->augType = at_leave; }; 568aug_type_cond: KW_When final { $$->loc = $1->loc; $$->augType = at_all; }; 569aug_type_cond: KW_InWhen final { $$->loc = $1->loc; $$->augType = at_start; }; 570aug_type_cond: KW_OutWhen final { $$->loc = $1->loc; $$->augType = at_leave; }; 571 572# 573# To state actions. 574# 575 576nonterm aug_type_to_state uses aug_type; 577 578aug_type_to_state: TK_StartToState 579 final { $$->loc = $1->loc; $$->augType = at_start_to_state; }; 580aug_type_to_state: '>' KW_To 581 final { $$->loc = $1->loc; $$->augType = at_start_to_state; }; 582 583aug_type_to_state: TK_NotStartToState 584 final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; }; 585aug_type_to_state: '<' KW_To 586 final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; }; 587 588aug_type_to_state: TK_AllToState 589 final { $$->loc = $1->loc; $$->augType = at_all_to_state; }; 590aug_type_to_state: '$' KW_To 591 final { $$->loc = $1->loc; $$->augType = at_all_to_state; }; 592 593aug_type_to_state: TK_FinalToState 594 final { $$->loc = $1->loc; $$->augType = at_final_to_state; }; 595aug_type_to_state: '%' KW_To 596 final { $$->loc = $1->loc; $$->augType = at_final_to_state; }; 597 598aug_type_to_state: TK_NotFinalToState 599 final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; }; 600aug_type_to_state: '@' KW_To 601 final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; }; 602 603aug_type_to_state: TK_MiddleToState 604 final { $$->loc = $1->loc; $$->augType = at_middle_to_state; }; 605aug_type_to_state: TK_Middle KW_To 606 final { $$->loc = $1->loc; $$->augType = at_middle_to_state; }; 607 608# 609# From state actions. 610# 611 612nonterm aug_type_from_state uses aug_type; 613 614aug_type_from_state: TK_StartFromState 615 final { $$->loc = $1->loc; $$->augType = at_start_from_state; }; 616aug_type_from_state: '>' KW_From 617 final { $$->loc = $1->loc; $$->augType = at_start_from_state; }; 618 619aug_type_from_state: TK_NotStartFromState 620 final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; }; 621aug_type_from_state: '<' KW_From 622 final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; }; 623 624aug_type_from_state: TK_AllFromState 625 final { $$->loc = $1->loc; $$->augType = at_all_from_state; }; 626aug_type_from_state: '$' KW_From 627 final { $$->loc = $1->loc; $$->augType = at_all_from_state; }; 628 629aug_type_from_state: TK_FinalFromState 630 final { $$->loc = $1->loc; $$->augType = at_final_from_state; }; 631aug_type_from_state: '%' KW_From 632 final { $$->loc = $1->loc; $$->augType = at_final_from_state; }; 633 634aug_type_from_state: TK_NotFinalFromState 635 final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; }; 636aug_type_from_state: '@' KW_From 637 final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; }; 638 639aug_type_from_state: TK_MiddleFromState 640 final { $$->loc = $1->loc; $$->augType = at_middle_from_state; }; 641aug_type_from_state: TK_Middle KW_From 642 final { $$->loc = $1->loc; $$->augType = at_middle_from_state; }; 643 644# 645# Eof state actions. 646# 647 648nonterm aug_type_eof uses aug_type; 649 650aug_type_eof: TK_StartEOF 651 final { $$->loc = $1->loc; $$->augType = at_start_eof; }; 652aug_type_eof: '>' KW_Eof 653 final { $$->loc = $1->loc; $$->augType = at_start_eof; }; 654 655aug_type_eof: TK_NotStartEOF 656 final { $$->loc = $1->loc; $$->augType = at_not_start_eof; }; 657aug_type_eof: '<' KW_Eof 658 final { $$->loc = $1->loc; $$->augType = at_not_start_eof; }; 659 660aug_type_eof: TK_AllEOF 661 final { $$->loc = $1->loc; $$->augType = at_all_eof; }; 662aug_type_eof: '$' KW_Eof 663 final { $$->loc = $1->loc; $$->augType = at_all_eof; }; 664 665aug_type_eof: TK_FinalEOF 666 final { $$->loc = $1->loc; $$->augType = at_final_eof; }; 667aug_type_eof: '%' KW_Eof 668 final { $$->loc = $1->loc; $$->augType = at_final_eof; }; 669 670aug_type_eof: TK_NotFinalEOF 671 final { $$->loc = $1->loc; $$->augType = at_not_final_eof; }; 672aug_type_eof: '@' KW_Eof 673 final { $$->loc = $1->loc; $$->augType = at_not_final_eof; }; 674 675aug_type_eof: TK_MiddleEOF 676 final { $$->loc = $1->loc; $$->augType = at_middle_eof; }; 677aug_type_eof: TK_Middle KW_Eof 678 final { $$->loc = $1->loc; $$->augType = at_middle_eof; }; 679 680# 681# Global error actions. 682# 683 684nonterm aug_type_gbl_error uses aug_type; 685 686aug_type_gbl_error: TK_StartGblError 687 final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; }; 688aug_type_gbl_error: '>' KW_Err 689 final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; }; 690 691aug_type_gbl_error: TK_NotStartGblError 692 final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; }; 693aug_type_gbl_error: '<' KW_Err 694 final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; }; 695 696aug_type_gbl_error: TK_AllGblError 697 final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; }; 698aug_type_gbl_error: '$' KW_Err 699 final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; }; 700 701aug_type_gbl_error: TK_FinalGblError 702 final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; }; 703aug_type_gbl_error: '%' KW_Err 704 final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; }; 705 706aug_type_gbl_error: TK_NotFinalGblError 707 final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; }; 708aug_type_gbl_error: '@' KW_Err 709 final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; }; 710 711aug_type_gbl_error: TK_MiddleGblError 712 final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; }; 713aug_type_gbl_error: TK_Middle KW_Err 714 final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; }; 715 716 717# 718# Local error actions. 719# 720 721nonterm aug_type_local_error uses aug_type; 722 723aug_type_local_error: TK_StartLocalError 724 final { $$->loc = $1->loc; $$->augType = at_start_local_error; }; 725aug_type_local_error: '>' KW_Lerr 726 final { $$->loc = $1->loc; $$->augType = at_start_local_error; }; 727 728aug_type_local_error: TK_NotStartLocalError 729 final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; }; 730aug_type_local_error: '<' KW_Lerr 731 final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; }; 732 733aug_type_local_error: TK_AllLocalError 734 final { $$->loc = $1->loc; $$->augType = at_all_local_error; }; 735aug_type_local_error: '$' KW_Lerr 736 final { $$->loc = $1->loc; $$->augType = at_all_local_error; }; 737 738aug_type_local_error: TK_FinalLocalError 739 final { $$->loc = $1->loc; $$->augType = at_final_local_error; }; 740aug_type_local_error: '%' KW_Lerr 741 final { $$->loc = $1->loc; $$->augType = at_final_local_error; }; 742 743aug_type_local_error: TK_NotFinalLocalError 744 final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; }; 745aug_type_local_error: '@' KW_Lerr 746 final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; }; 747 748aug_type_local_error: TK_MiddleLocalError 749 final { $$->loc = $1->loc; $$->augType = at_middle_local_error; }; 750aug_type_local_error: TK_Middle KW_Lerr 751 final { $$->loc = $1->loc; $$->augType = at_middle_local_error; }; 752 753 754type action_ref 755{ 756 Action *action; 757}; 758 759# Different ways to embed actions. A TK_Word is reference to an action given by 760# the user as a statement in the fsm specification. An action can also be 761# specified immediately. 762nonterm action_embed uses action_ref; 763 764action_embed: action_embed_word final { $$->action = $1->action; }; 765action_embed: '(' action_embed_word ')' final { $$->action = $2->action; }; 766action_embed: action_embed_block final { $$->action = $1->action; }; 767 768nonterm action_embed_word uses action_ref; 769 770action_embed_word: 771 TK_Word final { 772 /* Set the name in the actionDict. */ 773 Action *action = pd->actionDict.find( $1->data ); 774 if ( action != 0 ) { 775 /* Pass up the action element */ 776 $$->action = action; 777 } 778 else { 779 /* Will recover by returning null as the action. */ 780 error($1->loc) << "action lookup of \"" << $1->data << "\" failed" << endl; 781 $$->action = 0; 782 } 783 }; 784 785nonterm action_embed_block uses action_ref; 786 787action_embed_block: 788 '{' inline_block '}' final { 789 /* Create the action, add it to the list and pass up. */ 790 Action *newAction = new Action( $1->loc, 0, $2->inlineList, pd->nextCondId++ ); 791 pd->actionList.append( newAction ); 792 $$->action = newAction; 793 }; 794 795nonterm priority_name 796{ 797 int priorityName; 798}; 799 800# A specified priority name. Looks up the name in the current priority 801# dictionary. 802priority_name: 803 TK_Word final { 804 // Lookup/create the priority key. 805 PriorDictEl *priorDictEl; 806 if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) ) 807 pd->nextPriorKey += 1; 808 809 // Use the inserted/found priority key. 810 $$->priorityName = priorDictEl->value; 811 }; 812 813nonterm priority_aug 814{ 815 int priorityNum; 816}; 817 818# Priority change specs. 819priority_aug: 820 priority_aug_num final { 821 // Convert the priority number to a long. Check for overflow. 822 errno = 0; 823 //cerr << "PRIOR AUG: " << $1->token.data << endl; 824 long aug = strtol( $1->token.data, 0, 10 ); 825 if ( errno == ERANGE && aug == LONG_MAX ) { 826 /* Priority number too large. Recover by setting the priority to 0. */ 827 error($1->token.loc) << "priority number " << $1->token.data << 828 " overflows" << endl; 829 $$->priorityNum = 0; 830 } 831 else if ( errno == ERANGE && aug == LONG_MIN ) { 832 /* Priority number too large in the neg. Recover by using 0. */ 833 error($1->token.loc) << "priority number " << $1->token.data << 834 " underflows" << endl; 835 $$->priorityNum = 0; 836 } 837 else { 838 /* No overflow or underflow. */ 839 $$->priorityNum = aug; 840 } 841 }; 842 843nonterm priority_aug_num uses token_type; 844 845priority_aug_num: 846 TK_UInt final { 847 $$->token = *$1; 848 }; 849priority_aug_num: 850 '+' TK_UInt final { 851 $$->token.set( "+", 1 ); 852 $$->token.loc = $1->loc; 853 $$->token.append( *$2 ); 854 }; 855priority_aug_num: 856 '-' TK_UInt final { 857 $$->token.set( "-", 1 ); 858 $$->token.loc = $1->loc; 859 $$->token.append( *$2 ); 860 }; 861 862nonterm local_err_name 863{ 864 int error_name; 865}; 866 867local_err_name: 868 TK_Word final { 869 /* Lookup/create the priority key. */ 870 LocalErrDictEl *localErrDictEl; 871 if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) ) 872 pd->nextLocalErrKey += 1; 873 874 /* Use the inserted/found priority key. */ 875 $$->error_name = localErrDictEl->value; 876 }; 877 878 879 880# The fourth level of precedence. These are the trailing unary operators that 881# allow for repetition. 882 883nonterm factor_with_rep 884{ 885 FactorWithRep *factorWithRep; 886}; 887 888factor_with_rep: 889 factor_with_rep '*' final { 890 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 891 0, 0, FactorWithRep::StarType ); 892 }; 893factor_with_rep: 894 factor_with_rep TK_StarStar final { 895 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 896 0, 0, FactorWithRep::StarStarType ); 897 }; 898factor_with_rep: 899 factor_with_rep '?' final { 900 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 901 0, 0, FactorWithRep::OptionalType ); 902 }; 903factor_with_rep: 904 factor_with_rep '+' final { 905 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 906 0, 0, FactorWithRep::PlusType ); 907 }; 908factor_with_rep: 909 factor_with_rep '{' factor_rep_num '}' final { 910 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 911 $3->rep, 0, FactorWithRep::ExactType ); 912 }; 913factor_with_rep: 914 factor_with_rep '{' ',' factor_rep_num '}' final { 915 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 916 0, $4->rep, FactorWithRep::MaxType ); 917 }; 918factor_with_rep: 919 factor_with_rep '{' factor_rep_num ',' '}' final { 920 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 921 $3->rep, 0, FactorWithRep::MinType ); 922 }; 923factor_with_rep: 924 factor_with_rep '{' factor_rep_num ',' factor_rep_num '}' final { 925 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 926 $3->rep, $5->rep, FactorWithRep::RangeType ); 927 }; 928factor_with_rep: 929 factor_with_neg final { 930 $$->factorWithRep = new FactorWithRep( $1->factorWithNeg ); 931 }; 932 933nonterm factor_rep_num 934{ 935 int rep; 936}; 937 938factor_rep_num: 939 TK_UInt final { 940 // Convert the priority number to a long. Check for overflow. 941 errno = 0; 942 long rep = strtol( $1->data, 0, 10 ); 943 if ( errno == ERANGE && rep == LONG_MAX ) { 944 // Repetition too large. Recover by returing repetition 1. */ 945 error($1->loc) << "repetition number " << $1->data << " overflows" << endl; 946 $$->rep = 1; 947 } 948 else { 949 // Cannot be negative, so no overflow. 950 $$->rep = rep; 951 } 952 }; 953 954 955# 956# The fifth level up in precedence. Negation. 957# 958 959nonterm factor_with_neg 960{ 961 FactorWithNeg *factorWithNeg; 962}; 963 964factor_with_neg: 965 '!' factor_with_neg final { 966 $$->factorWithNeg = new FactorWithNeg( $1->loc, 967 $2->factorWithNeg, FactorWithNeg::NegateType ); 968 }; 969factor_with_neg: 970 '^' factor_with_neg final { 971 $$->factorWithNeg = new FactorWithNeg( $1->loc, 972 $2->factorWithNeg, FactorWithNeg::CharNegateType ); 973 }; 974factor_with_neg: 975 factor final { 976 $$->factorWithNeg = new FactorWithNeg( $1->factor ); 977 }; 978 979nonterm factor 980{ 981 Factor *factor; 982}; 983 984factor: 985 TK_Literal final { 986 /* Create a new factor node going to a concat literal. */ 987 $$->factor = new Factor( new Literal( *$1, Literal::LitString ) ); 988 }; 989factor: 990 alphabet_num final { 991 /* Create a new factor node going to a literal number. */ 992 $$->factor = new Factor( new Literal( $1->token, Literal::Number ) ); 993 }; 994factor: 995 TK_Word final { 996 /* Find the named graph. */ 997 GraphDictEl *gdNode = pd->graphDict.find( $1->data ); 998 if ( gdNode == 0 ) { 999 /* Recover by returning null as the factor node. */ 1000 error($1->loc) << "graph lookup of \"" << $1->data << "\" failed" << endl; 1001 $$->factor = 0; 1002 } 1003 else if ( gdNode->isInstance ) { 1004 /* Recover by retuning null as the factor node. */ 1005 error($1->loc) << "references to graph instantiations not allowed " 1006 "in expressions" << endl; 1007 $$->factor = 0; 1008 } 1009 else { 1010 /* Create a factor node that is a lookup of an expression. */ 1011 $$->factor = new Factor( $1->loc, gdNode->value ); 1012 } 1013 }; 1014factor: 1015 RE_SqOpen regular_expr_or_data RE_SqClose final { 1016 /* Create a new factor node going to an OR expression. */ 1017 $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock ) ); 1018 }; 1019factor: 1020 RE_SqOpenNeg regular_expr_or_data RE_SqClose final { 1021 /* Create a new factor node going to a negated OR expression. */ 1022 $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ) ); 1023 }; 1024factor: 1025 RE_Slash regular_expr RE_Slash final { 1026 if ( $3->length > 1 ) { 1027 for ( char *p = $3->data; *p != 0; p++ ) { 1028 if ( *p == 'i' ) 1029 $2->regExpr->caseInsensitive = true; 1030 } 1031 } 1032 1033 /* Create a new factor node going to a regular exp. */ 1034 $$->factor = new Factor( $2->regExpr ); 1035 }; 1036factor: 1037 range_lit TK_DotDot range_lit final { 1038 /* Create a new factor node going to a range. */ 1039 $$->factor = new Factor( new Range( $1->literal, $3->literal ) ); 1040 }; 1041factor: 1042 '(' join ')' final { 1043 /* Create a new factor going to a parenthesized join. */ 1044 $$->factor = new Factor( $2->join ); 1045 $2->join->loc = $1->loc; 1046 }; 1047 1048nonterm range_lit 1049{ 1050 Literal *literal; 1051}; 1052 1053# Literals which can be the end points of ranges. 1054range_lit: 1055 TK_Literal final { 1056 /* Range literas must have only one char. We restrict this in the parse tree. */ 1057 $$->literal = new Literal( *$1, Literal::LitString ); 1058 }; 1059range_lit: 1060 alphabet_num final { 1061 /* Create a new literal number. */ 1062 $$->literal = new Literal( $1->token, Literal::Number ); 1063 }; 1064 1065nonterm alphabet_num uses token_type; 1066 1067# Any form of a number that can be used as a basic machine. */ 1068alphabet_num: 1069 TK_UInt final { 1070 $$->token = *$1; 1071 }; 1072alphabet_num: 1073 '-' TK_UInt final { 1074 $$->token.set( "-", 1 ); 1075 $$->token.loc = $1->loc; 1076 $$->token.append( *$2 ); 1077 }; 1078alphabet_num: 1079 TK_Hex final { 1080 $$->token = *$1; 1081 }; 1082# 1083# Regular Expressions. 1084# 1085 1086nonterm regular_expr 1087{ 1088 RegExpr *regExpr; 1089}; 1090 1091# Parser for regular expression fsms. Any number of expression items which 1092# generally gives a machine one character long or one character long stared. 1093regular_expr: 1094 regular_expr regular_expr_item final { 1095 /* An optimization to lessen the tree size. If a non-starred char is 1096 * directly under the left side on the right and the right side is 1097 * another non-starred char then paste them together and return the 1098 * left side. Otherwise just put the two under a new reg exp node. */ 1099 if ( $2->reItem->type == ReItem::Data && !$2->reItem->star && 1100 $1->regExpr->type == RegExpr::RecurseItem && 1101 $1->regExpr->item->type == ReItem::Data && !$1->regExpr->item->star ) 1102 { 1103 /* Append the right side to the right side of the left and toss the 1104 * right side. */ 1105 $1->regExpr->item->token.append( $2->reItem->token ); 1106 delete $2->reItem; 1107 $$->regExpr = $1->regExpr; 1108 } 1109 else { 1110 $$->regExpr = new RegExpr( $1->regExpr, $2->reItem ); 1111 } 1112 }; 1113regular_expr: 1114 final { 1115 /* Can't optimize the tree. */ 1116 $$->regExpr = new RegExpr(); 1117 }; 1118 1119nonterm regular_expr_item 1120{ 1121 ReItem *reItem; 1122}; 1123 1124# RegularExprItems can be a character spec with an optional staring of the char. 1125regular_expr_item: 1126 regular_expr_char RE_Star final { 1127 $1->reItem->star = true; 1128 $$->reItem = $1->reItem; 1129 }; 1130regular_expr_item: 1131 regular_expr_char final { 1132 $$->reItem = $1->reItem; 1133 }; 1134 1135nonterm regular_expr_char 1136{ 1137 ReItem *reItem; 1138}; 1139 1140# A character spec can be a set of characters inside of square parenthesis, a 1141# dot specifying any character or some explicitly stated character. 1142regular_expr_char: 1143 RE_SqOpen regular_expr_or_data RE_SqClose final { 1144 $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock ); 1145 }; 1146regular_expr_char: 1147 RE_SqOpenNeg regular_expr_or_data RE_SqClose final { 1148 $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ); 1149 }; 1150regular_expr_char: 1151 RE_Dot final { 1152 $$->reItem = new ReItem( $1->loc, ReItem::Dot ); 1153 }; 1154regular_expr_char: 1155 RE_Char final { 1156 $$->reItem = new ReItem( $1->loc, *$1 ); 1157 }; 1158 1159# The data inside of a [] expression in a regular expression. Accepts any 1160# number of characters or ranges. */ 1161nonterm regular_expr_or_data 1162{ 1163 ReOrBlock *reOrBlock; 1164}; 1165 1166regular_expr_or_data: 1167 regular_expr_or_data regular_expr_or_char final { 1168 /* An optimization to lessen the tree size. If an or char is directly 1169 * under the left side on the right and the right side is another or 1170 * char then paste them together and return the left side. Otherwise 1171 * just put the two under a new or data node. */ 1172 if ( $2->reOrItem->type == ReOrItem::Data && 1173 $1->reOrBlock->type == ReOrBlock::RecurseItem && 1174 $1->reOrBlock->item->type == ReOrItem::Data ) 1175 { 1176 /* Append the right side to right side of the left and toss the 1177 * right side. */ 1178 $1->reOrBlock->item->token.append( $2->reOrItem->token ); 1179 delete $2->reOrItem; 1180 $$->reOrBlock = $1->reOrBlock; 1181 } 1182 else { 1183 /* Can't optimize, put the left and right under a new node. */ 1184 $$->reOrBlock = new ReOrBlock( $1->reOrBlock, $2->reOrItem ); 1185 } 1186 }; 1187regular_expr_or_data: 1188 final { 1189 $$->reOrBlock = new ReOrBlock(); 1190 }; 1191 1192# A single character inside of an or expression. Can either be a character or a 1193# set of characters. 1194nonterm regular_expr_or_char 1195{ 1196 ReOrItem *reOrItem; 1197}; 1198 1199regular_expr_or_char: 1200 RE_Char final { 1201 $$->reOrItem = new ReOrItem( $1->loc, *$1 ); 1202 }; 1203regular_expr_or_char: 1204 RE_Char RE_Dash RE_Char final { 1205 $$->reOrItem = new ReOrItem( $2->loc, $1->data[0], $3->data[0] ); 1206 }; 1207 1208# 1209# Inline Lists for inline host code. 1210# 1211 1212type inline_list 1213{ 1214 InlineList *inlineList; 1215}; 1216 1217nonterm inline_block uses inline_list; 1218 1219inline_block: 1220 inline_block inline_block_item 1221 final { 1222 /* Append the item to the list, return the list. */ 1223 $$->inlineList = $1->inlineList; 1224 $$->inlineList->append( $2->inlineItem ); 1225 }; 1226 1227inline_block: 1228 final { 1229 /* Start with empty list. */ 1230 $$->inlineList = new InlineList; 1231 }; 1232 1233type inline_item 1234{ 1235 InlineItem *inlineItem; 1236}; 1237 1238nonterm inline_block_item uses inline_item; 1239nonterm inline_block_interpret uses inline_item; 1240 1241inline_block_item: 1242 inline_expr_any 1243 final { 1244 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); 1245 }; 1246 1247inline_block_item: 1248 inline_block_symbol 1249 final { 1250 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); 1251 }; 1252 1253inline_block_item: 1254 inline_block_interpret 1255 final { 1256 /* Pass the inline item up. */ 1257 $$->inlineItem = $1->inlineItem; 1258 }; 1259 1260nonterm inline_block_symbol uses token_type; 1261 1262inline_block_symbol: ',' final { $$->token = *$1; }; 1263inline_block_symbol: ';' final { $$->token = *$1; }; 1264inline_block_symbol: '(' final { $$->token = *$1; }; 1265inline_block_symbol: ')' final { $$->token = *$1; }; 1266inline_block_symbol: '*' final { $$->token = *$1; }; 1267inline_block_symbol: TK_NameSep final { $$->token = *$1; }; 1268 1269# Interpreted statements in a struct block. */ 1270inline_block_interpret: 1271 inline_expr_interpret final { 1272 /* Pass up interpreted items of inline expressions. */ 1273 $$->inlineItem = $1->inlineItem; 1274 }; 1275inline_block_interpret: 1276 KW_Hold ';' final { 1277 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Hold ); 1278 }; 1279inline_block_interpret: 1280 KW_Exec inline_expr ';' final { 1281 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Exec ); 1282 $$->inlineItem->children = $2->inlineList; 1283 }; 1284inline_block_interpret: 1285 KW_Goto state_ref ';' final { 1286 $$->inlineItem = new InlineItem( $1->loc, 1287 new NameRef(nameRef), InlineItem::Goto ); 1288 }; 1289inline_block_interpret: 1290 KW_Goto '*' inline_expr ';' final { 1291 $$->inlineItem = new InlineItem( $1->loc, InlineItem::GotoExpr ); 1292 $$->inlineItem->children = $3->inlineList; 1293 }; 1294inline_block_interpret: 1295 KW_Next state_ref ';' final { 1296 $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Next ); 1297 }; 1298inline_block_interpret: 1299 KW_Next '*' inline_expr ';' final { 1300 $$->inlineItem = new InlineItem( $1->loc, InlineItem::NextExpr ); 1301 $$->inlineItem->children = $3->inlineList; 1302 }; 1303inline_block_interpret: 1304 KW_Call state_ref ';' final { 1305 $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Call ); 1306 }; 1307inline_block_interpret: 1308 KW_Call '*' inline_expr ';' final { 1309 $$->inlineItem = new InlineItem( $1->loc, InlineItem::CallExpr ); 1310 $$->inlineItem->children = $3->inlineList; 1311 }; 1312inline_block_interpret: 1313 KW_Ret ';' final { 1314 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Ret ); 1315 }; 1316inline_block_interpret: 1317 KW_Break ';' final { 1318 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Break ); 1319 }; 1320 1321nonterm inline_expr uses inline_list; 1322 1323inline_expr: 1324 inline_expr inline_expr_item 1325 final { 1326 $$->inlineList = $1->inlineList; 1327 $$->inlineList->append( $2->inlineItem ); 1328 }; 1329inline_expr: 1330 final { 1331 /* Init the list used for this expr. */ 1332 $$->inlineList = new InlineList; 1333 }; 1334 1335nonterm inline_expr_item uses inline_item; 1336 1337inline_expr_item: 1338 inline_expr_any 1339 final { 1340 /* Return a text segment. */ 1341 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); 1342 }; 1343inline_expr_item: 1344 inline_expr_symbol 1345 final { 1346 /* Return a text segment, must heap alloc the text. */ 1347 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); 1348 }; 1349inline_expr_item: 1350 inline_expr_interpret 1351 final{ 1352 /* Pass the inline item up. */ 1353 $$->inlineItem = $1->inlineItem; 1354 }; 1355 1356nonterm inline_expr_any uses token_type; 1357 1358inline_expr_any: IL_WhiteSpace try { $$->token = *$1; }; 1359inline_expr_any: IL_Comment try { $$->token = *$1; }; 1360inline_expr_any: IL_Literal try { $$->token = *$1; }; 1361inline_expr_any: IL_Symbol try { $$->token = *$1; }; 1362inline_expr_any: TK_UInt try { $$->token = *$1; }; 1363inline_expr_any: TK_Hex try { $$->token = *$1; }; 1364inline_expr_any: TK_Word try { $$->token = *$1; }; 1365 1366# Anything in a ExecValExpr that is not dynamically allocated. This includes 1367# all special symbols caught in inline code except the semi. 1368 1369nonterm inline_expr_symbol uses token_type; 1370 1371inline_expr_symbol: ',' try { $$->token = *$1; }; 1372inline_expr_symbol: '(' try { $$->token = *$1; }; 1373inline_expr_symbol: ')' try { $$->token = *$1; }; 1374inline_expr_symbol: '*' try { $$->token = *$1; }; 1375inline_expr_symbol: TK_NameSep try { $$->token = *$1; }; 1376 1377nonterm inline_expr_interpret uses inline_item; 1378 1379inline_expr_interpret: 1380 KW_PChar 1381 final { 1382 $$->inlineItem = new InlineItem( $1->loc, InlineItem::PChar ); 1383 }; 1384inline_expr_interpret: 1385 KW_Char 1386 final { 1387 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Char ); 1388 }; 1389inline_expr_interpret: 1390 KW_CurState 1391 final { 1392 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Curs ); 1393 }; 1394inline_expr_interpret: 1395 KW_TargState 1396 final { 1397 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Targs ); 1398 }; 1399inline_expr_interpret: 1400 KW_Entry '(' state_ref ')' 1401 final { 1402 $$->inlineItem = new InlineItem( $1->loc, 1403 new NameRef(nameRef), InlineItem::Entry ); 1404 }; 1405 1406# A local state reference. Cannot have :: prefix. 1407local_state_ref: 1408 no_name_sep state_ref_names; 1409 1410# Clear the name ref structure. 1411no_name_sep: 1412 final { 1413 nameRef.empty(); 1414 }; 1415 1416# A qualified state reference. 1417state_ref: opt_name_sep state_ref_names; 1418 1419# Optional leading name separator. 1420opt_name_sep: 1421 TK_NameSep 1422 final { 1423 /* Insert an initial null pointer val to indicate the existence of the 1424 * initial name seperator. */ 1425 nameRef.setAs( 0 ); 1426 }; 1427opt_name_sep: 1428 final { 1429 nameRef.empty(); 1430 }; 1431 1432# List of names separated by :: 1433state_ref_names: 1434 state_ref_names TK_NameSep TK_Word 1435 final { 1436 nameRef.append( $3->data ); 1437 }; 1438state_ref_names: 1439 TK_Word 1440 final { 1441 nameRef.append( $1->data ); 1442 }; 1443 1444}%% 1445 1446%%{ 1447 write types; 1448 write data; 1449}%% 1450 1451void Parser::init() 1452{ 1453 %% write init; 1454} 1455 1456int Parser::parseLangEl( int type, const Token *token ) 1457{ 1458 %% write exec; 1459 return errCount == 0 ? 0 : -1; 1460} 1461 1462void Parser::tryMachineDef( InputLoc &loc, char *name, 1463 MachineDef *machineDef, bool isInstance ) 1464{ 1465 GraphDictEl *newEl = pd->graphDict.insert( name ); 1466 if ( newEl != 0 ) { 1467 /* New element in the dict, all good. */ 1468 newEl->value = new VarDef( name, machineDef ); 1469 newEl->isInstance = isInstance; 1470 newEl->loc = loc; 1471 newEl->value->isExport = exportContext[exportContext.length()-1]; 1472 1473 /* It it is an instance, put on the instance list. */ 1474 if ( isInstance ) 1475 pd->instanceList.append( newEl ); 1476 } 1477 else { 1478 // Recover by ignoring the duplicate. 1479 error(loc) << "fsm \"" << name << "\" previously defined" << endl; 1480 } 1481} 1482 1483ostream &Parser::parse_error( int tokId, Token &token ) 1484{ 1485 /* Maintain the error count. */ 1486 gblErrorCount += 1; 1487 1488 cerr << token.loc << ": "; 1489 cerr << "at token "; 1490 if ( tokId < 128 ) 1491 cerr << "\"" << Parser_lelNames[tokId] << "\""; 1492 else 1493 cerr << Parser_lelNames[tokId]; 1494 if ( token.data != 0 ) 1495 cerr << " with data \"" << token.data << "\""; 1496 cerr << ": "; 1497 1498 return cerr; 1499} 1500 1501int Parser::token( InputLoc &loc, int tokId, char *tokstart, int toklen ) 1502{ 1503 Token token; 1504 token.data = tokstart; 1505 token.length = toklen; 1506 token.loc = loc; 1507 int res = parseLangEl( tokId, &token ); 1508 if ( res < 0 ) { 1509 parse_error(tokId, token) << "parse error" << endl; 1510 exit(1); 1511 } 1512 return res; 1513} 1514