1 2%{ 3/* This file is part of kdev-pg-qt 4 Copyright (C) 2005 Roberto Raggi <roberto@kdevelop.org> 5 Copyright (C) 2006 Jakob Petsovits <jpetso@gmx.at> 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library 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 GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public License 18 along with this library; see the file COPYING.LIB. If not, write to 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 Boston, MA 02110-1301, USA. 21*/ 22 23#include "kdev-pg.h" 24#include "kdev-pg-clone-tree.h" 25#include "kdev-pg-regexp.h" 26#include "kdev-pg-unicode-loader.h" 27#include "kdev-pg-checker.h" 28 29#include <QFile> 30#include <cassert> 31 32extern int yylex(); 33extern void yyerror(const char* msg); 34extern int yyLine; 35 36QString lexerEnv; 37 38namespace KDevPG 39{ 40 extern QFile file; 41 extern QTextStream checkOut; 42} 43 44KDevPG::Model::OperatorItem *operatorNode = 0; 45QString r; 46 47%} 48 49%union { 50 KDevPG::Model::Node *item; 51 char* str; 52 KDevPG::Model::VariableDeclarationItem::DeclarationType declarationType; 53 KDevPG::Model::VariableDeclarationItem::StorageType storageType; 54 KDevPG::Model::VariableDeclarationItem::VariableType variableType; 55 KDevPG::Model::Operator *operatorInformation; 56 KDevPG::GNFA *nfa; 57} 58 59%token T_IDENTIFIER T_ARROW T_TERMINAL T_CODE T_STRING T_UNQUOTED_STRING T_NUMBER ';' 60%token T_TOKEN_DECLARATION T_TOKEN_STREAM_DECLARATION T_NAMESPACE_DECLARATION 61%token T_PARSERCLASS_DECLARATION T_LEXERCLASS_DECLARATION 62%token T_PUBLIC T_PRIVATE T_PROTECTED T_DECLARATION T_BITS 63%token T_CONSTRUCTOR T_DESTRUCTOR T_TRY_RECOVER T_TRY_ROLLBACK T_CATCH 64%token T_RULE_ARGUMENTS T_MEMBER T_TEMPORARY T_ARGUMENT T_EXPORT_MACRO 65%token T_NODE T_NODE_SEQUENCE T_TOKEN T_VARIABLE T_EXPORT_MACRO_HEADER 66%token T_AST_DECLARATION 67%token T_PARSER_DECLARATION_HEADER T_PARSER_BITS_HEADER T_AST_HEADER 68%token T_LEXER_DECLARATION_HEADER T_LEXER_BITS_HEADER 69%token T_PARSER_BASE T_AST_BASE T_LEXER_BASE 70%token T_BIN T_PRE T_POST T_TERN 71%token T_LOPR T_ROPR 72%token T_LEFT_ASSOC T_RIGHT_ASSOC T_IS_LEFT_ASSOC T_IS_RIGHT_ASSOC T_PRIORITY 73%token T_PAREN 74%token T_INLINE 75%token T_LEXER T_INPUT_STREAM T_INPUT_ENCODING T_TABLE_LEXER T_SEQUENCE_LEXER 76%token T_NAMED_REGEXP T_CONTINUE T_RANGE T_FAIL T_LOOKAHEAD T_BARRIER 77%token T_ENTER_RULE_SET T_LEAVE_RULE_SET 78 79%type<str> T_IDENTIFIER T_TERMINAL T_CODE T_STRING T_UNQUOTED_STRING T_RULE_ARGUMENTS T_NUMBER T_NAMED_REGEXP T_RANGE 80%type<str> name code_opt rule_arguments_opt priority assoc opt_lexer_action 81%type<item> item primary_item try_item primary_atom unary_item 82%type<item> postfix_item option_item item_sequence conditional_item 83%type<item> member_declaration_rest variableDeclarations variableDeclaration operatorRule 84%type<declarationType> declarationType_opt 85%type<storageType> scope storageType 86%type<variableType> variableType 87/* %type<void> operatorDeclaration operatorDeclarations operatorRule */ 88%type<operatorInformation> operator 89%type<nfa> regexp regexp1 regexp2 regexp3 regexp4 regexp5 regexp6 regexp7 aregexp aregexp1 aregexp2 aregexp3 aregexp4 aregexp5 aregexp6 aregexp7 90 91%% 92 93system 94 : code_opt { KDevPG::globalSystem.decl = $1; } 95 declarations 96 rules 97 code_opt { KDevPG::globalSystem.bits += $5; } 98 ; 99 100declarations 101 : declaration 102 | declarations declaration 103 ; 104 105declaration 106 : T_PARSERCLASS_DECLARATION member_declaration_rest 107 { KDevPG::globalSystem.pushParserClassMember($2); } 108 | T_PARSERCLASS_DECLARATION '(' T_BITS ')' T_CODE 109 { KDevPG::globalSystem.bits += $5; } 110 | T_LEXERCLASS_DECLARATION member_declaration_rest 111 { KDevPG::globalSystem.pushLexerClassMember($2); } 112 | T_LEXERCLASS_DECLARATION '(' T_BITS ')' T_CODE 113 { KDevPG::globalSystem.lexerBits += $5; } 114 | T_TOKEN_DECLARATION declared_tokens ';' 115 | T_TABLE_LEXER 116 { if(KDevPG::globalSystem.hasLexer) 117 { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%table_lexer) before any lexer rules"; exit(-1); } 118 switch(KDevPG::GDFA::type) 119 { 120 case KDevPG::SAscii: KDevPG::GDFA::type = KDevPG::TAscii; break; 121 case KDevPG::SLatin1: KDevPG::GDFA::type = KDevPG::TLatin1; break; 122 case KDevPG::SUtf8: KDevPG::GDFA::type = KDevPG::TUtf8; break; 123 case KDevPG::SUcs2: KDevPG::GDFA::type = KDevPG::TUcs2; break; 124 case KDevPG::SUtf16: KDevPG::GDFA::type = KDevPG::TUtf16; break; 125/* case KDevPG::SUcs4: KDevPG::GDFA::type = KDevPG::TUcs4; break; */ 126 default: /* empty */; 127 } 128 } 129 | T_SEQUENCE_LEXER 130 { if(KDevPG::globalSystem.hasLexer) 131 { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%sequence_lexer) before any lexer rules"; exit(-1); } 132 switch(KDevPG::GDFA::type) 133 { 134 case KDevPG::TAscii: KDevPG::GDFA::type = KDevPG::SAscii; break; 135 case KDevPG::TLatin1: KDevPG::GDFA::type = KDevPG::SLatin1; break; 136 case KDevPG::TUtf8: KDevPG::GDFA::type = KDevPG::SUtf8; break; 137 case KDevPG::TUcs2: KDevPG::GDFA::type = KDevPG::SUcs2; break; 138 case KDevPG::TUtf16: KDevPG::GDFA::type = KDevPG::SUtf16; break; 139/* case KDevPG::TUcs4: KDevPG::GDFA::type = KDevPG::SUcs4; break; */ 140 default: /* empty */; 141 } 142 } 143 | T_INPUT_ENCODING T_STRING 144 { 145 if(KDevPG::globalSystem.hasLexer) 146 { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%sequence_lexer) before any lexer rules"; exit(-1); } 147 int base = (KDevPG::GDFA::type / 4) * 4; // warning: magic constant: number of different codecs 148 QString str = $2; 149 str = str.toLower(); 150 str.replace('-', ""); 151 if(str == "ascii") 152 /* base += 0*/; 153 else if(str == "latin1") 154 base += 1; 155 else if(str == "utf8") 156 base += 2; 157 else if(str == "ucs2") 158 base += 3; 159 else if(str == "utf16") 160 base += 4; 161 else if(str == "ucs4" || str == "utf32") 162 base += 5; 163 else 164 { 165 KDevPG::checkOut << "** ERROR unknown codec ``" << $2 << "''" << endl; 166 exit(-1); 167 } 168 KDevPG::GDFA::type = KDevPG::AutomatonType(base); 169 } 170 | T_TOKEN_STREAM_DECLARATION T_IDENTIFIER ';' 171 { KDevPG::globalSystem.tokenStream = $2; } 172 | T_EXPORT_MACRO T_STRING 173 { KDevPG::globalSystem.exportMacro = $2; } 174 | T_EXPORT_MACRO_HEADER T_STRING 175 { KDevPG::globalSystem.exportMacroHeader = $2; } 176 | T_NAMESPACE_DECLARATION T_CODE 177 { KDevPG::globalSystem.namespaceCode = $2; } 178 | T_AST_DECLARATION T_CODE 179 { KDevPG::globalSystem.astCode = $2; } 180 | T_PARSER_DECLARATION_HEADER T_STRING 181 { KDevPG::globalSystem.pushParserDeclarationHeader($2); } 182 | T_PARSER_BITS_HEADER T_STRING 183 { KDevPG::globalSystem.pushParserBitsHeader($2); } 184 | T_AST_HEADER T_STRING 185 { KDevPG::globalSystem.pushAstHeader($2); } 186 | T_LEXER_DECLARATION_HEADER T_STRING 187 { KDevPG::globalSystem.pushLexerDeclarationHeader($2); } 188 | T_INPUT_STREAM T_STRING 189 { KDevPG::globalSystem.inputStream = $2; } 190 | T_LEXER_BITS_HEADER T_STRING 191 { KDevPG::globalSystem.pushLexerBitsHeader($2); } 192 | T_AST_BASE T_IDENTIFIER T_STRING 193 { KDevPG::globalSystem.astBaseClasses[$2] = $3; } 194 | T_PARSER_BASE T_STRING 195 { KDevPG::globalSystem.parserBaseClass = $2; } 196 | T_LEXER_BASE T_STRING 197 { KDevPG::globalSystem.lexerBaseClass = $2; } 198 | T_LEXER T_STRING { KDevPG::globalSystem.hasLexer = true; lexerEnv = $2; if(KDevPG::globalSystem.lexerActions[lexerEnv].empty()) KDevPG::globalSystem.lexerActions[lexerEnv].push_back("qDebug() << \"error\"; exit(-1);"); } T_ARROW lexer_declaration_rest ';' 199 | T_LEXER { KDevPG::globalSystem.hasLexer = true; KDevPG::loadUnicodeData(); lexerEnv = "start"; if(KDevPG::globalSystem.lexerActions["start"].empty()) KDevPG::globalSystem.lexerActions["start"].push_back("qDebug() << \"error\"; exit(-1);"); } T_ARROW lexer_declaration_rest ';' 200 ; 201 202lexer_declaration_rest 203 : regexp T_ARROW T_IDENTIFIER ';' 204 { KDevPG::globalSystem.regexpById[$3] = $1; 205 } lexer_declaration_rest 206 | regexp code_opt opt_lexer_action ';' 207 { 208 if($1->acceptsEpsilon()) 209 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << endl; 210 else if($1->isEmpty()) 211 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << endl; 212 QString s = QString($2) + QString(r); 213 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1); 214 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s); 215 } lexer_declaration_rest 216 | regexp T_LOOKAHEAD '(' regexp ')' code_opt opt_lexer_action ';' 217 { 218 if($1->acceptsEpsilon()) 219 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << endl; 220 else if($1->isEmpty()) 221 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << endl; 222 bool ignore = false; 223 auto minLen = $4->minLength(), maxLen = $4->maxLength(); 224 if(minLen == 0) 225 { 226 KDevPG::checkOut << "** WARNING Lexer rule specifying epsilon-lookahead at line " << yyLine << ", ignore the lookahead." << endl; 227 ignore = true; 228 } 229 else if(minLen != maxLen) 230 { 231 KDevPG::checkOut << "** WARNING Invalid lookahead (no fixed length) at line " << yyLine << " (min length: " << (minLen == -1 ? "none" : QString::number(minLen)) << ", max length: " << (maxLen == -2 ? "infinity" : (maxLen == -1 ? "none" : QString::number(maxLen))) << "), ignore the lookahead." << endl; 232 ignore = true; 233 } 234 if(ignore) 235 { 236 QString s = QString($6) + QString(r); 237 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1); 238 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s); 239 } 240 else 241 { 242 QString s = "Iterator::plain() -= " + QString::number(minLen) + "; " + QString($6) + QString(r); 243 *$1 <<= *$4; 244 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1); 245 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s); 246 } 247 } lexer_declaration_rest 248 | regexp T_BARRIER '(' regexp ')' code_opt opt_lexer_action ';' 249 { 250 if($1->acceptsEpsilon()) 251 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << endl; 252 else if($1->isEmpty()) 253 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << endl; 254 bool ignore = false; 255 auto minLen = $4->minLength(), maxLen = $4->maxLength(); 256 if(minLen == 0) 257 { 258 KDevPG::checkOut << "** WARNING Lexer rule specifying epsilon-barrier at line " << yyLine << ", ignore the barrier." << endl; 259 ignore = true; 260 } 261 else if(minLen != maxLen) 262 { 263 KDevPG::checkOut << "** WARNING Invalid barrier (no fixed length) at line " << yyLine << " (min length: " << (minLen == -1 ? "none" : QString::number(minLen)) << ", max length: " << (maxLen == -2 ? "infinity" : (maxLen == -1 ? "none" : QString::number(maxLen))) << "), ignore the barrier." << endl; 264 ignore = true; 265 } 266 if(ignore) 267 { 268 QString s = QString($6) + QString(r); 269 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1); 270 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s); 271 } 272 else 273 { 274 KDevPG::GNFA exclude = KDevPG::GNFA::anything(); 275 exclude <<= *$4; 276 exclude <<= KDevPG::GNFA::anything(); 277 KDevPG::GNFA *staying = new KDevPG::GNFA(*$1); 278 *staying ^= exclude; 279 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back(staying); 280 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(QString($6) + QString(r)); 281 // barrier should not get read partially 282 exclude <<= KDevPG::GNFA::anyChar(); 283 *$1 <<= *$4; 284 *$1 ^= exclude; 285 QString s = "Iterator::plain() -= " + QString::number(minLen) + "; " + QString($6) + QString(r); 286 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1); 287 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s); 288 } 289 } lexer_declaration_rest 290 | T_FAIL T_CODE 291 { 292 KDevPG::globalSystem.lexerActions[lexerEnv][0] = QString($2); 293 } lexer_declaration_rest 294 | T_ENTER_RULE_SET T_CODE 295 { 296 KDevPG::globalSystem.enteringCode[lexerEnv] = QString($2); 297 } lexer_declaration_rest 298 | T_LEAVE_RULE_SET T_CODE 299 { 300 KDevPG::globalSystem.leavingCode[lexerEnv] = QString($2); 301 } lexer_declaration_rest 302 | /* empty */ 303 ; 304 305opt_lexer_action 306 : T_TERMINAL { 307 r = "\nlxRETURN(" + QString($1) + ")\n"; 308 } 309 | T_CONTINUE { 310 r = "\nlxCONTINUE;\n"; 311 } 312 | /* empty */ { r = "\nlxSKIP\n"; } 313 ; 314 315regexp 316 : regexp '|' regexp1 { $$ = new KDevPG::GNFA(*$1 |= *$3); delete $1; delete $3; } 317 | regexp1 { $$ = $1; } 318 ; 319 320regexp1 321 : regexp1 '&' regexp2 { $$ = new KDevPG::GNFA(*$1 &= *$3); delete $1; delete $3; } 322 | regexp2 { $$ = $1; } 323 ; 324 325regexp2 326 : regexp3 '^' regexp2 { $$ = new KDevPG::GNFA(*$1 ^= *$3); delete $1; delete $3; } 327 | regexp3 { $$ = $1; } 328 ; 329 330regexp3 331 : '~' regexp3 { $$ = new KDevPG::GNFA($2->negate()); delete $2; } 332 | '?' regexp3 { $$ = new KDevPG::GNFA(*$2 |= KDevPG::GNFA::emptyWord()); delete $2; } 333 | regexp4 { $$ = $1; } 334 ; 335 336regexp4 337 : regexp4 regexp5 { $$ = new KDevPG::GNFA(*$1 <<= *$2); delete $1; delete $2; } 338 | regexp5 { $$ = $1; } 339 ; 340 341regexp5 342 : regexp5 '@' regexp6 { $$ = new KDevPG::GNFA(*$1); KDevPG::GNFA *tmp = new KDevPG::GNFA(*$3 <<= *$1); **tmp; *$$ <<= *tmp; delete tmp; delete $1; delete $3; } 343 | regexp6 { $$ = $1; } 344 ; 345 346regexp6 347 : regexp6 '*' { $$ = new KDevPG::GNFA(**$1); delete $1; } 348 | regexp6 '+' { $$ = new KDevPG::GNFA(*$1); **$$; *$$ <<= *$1; delete $1; } 349 | regexp7 { $$ = $1; } 350 ; 351 352regexp7 353 : '(' regexp ')' { $$ = new KDevPG::GNFA(*$2); delete $2; } 354 | '[' aregexp ']' { $$ = $2; } 355 | '.' { $$ = new KDevPG::GNFA(KDevPG::GNFA::anyChar()); } 356 | T_STRING { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); } 357 | T_UNQUOTED_STRING { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); } 358 | T_NAMED_REGEXP { 359 if(!KDevPG::globalSystem.regexpById.contains($1)) 360 { 361 KDevPG::checkOut << "** ERROR: no named regexp " << $1 << endl; 362 exit(-1); 363 } 364 KDevPG::GNFA *regexp = KDevPG::globalSystem.regexpById[$1]; 365 if(!KDevPG::globalSystem.dfaForNfa.contains(regexp)) 366 { 367 KDevPG::globalSystem.dfaForNfa[regexp] = new KDevPG::GDFA(regexp->dfa()); 368 KDevPG::globalSystem.dfaForNfa[regexp]->minimize(); 369 *regexp = KDevPG::globalSystem.dfaForNfa[regexp]->nfa(); 370 } 371 $$ = new KDevPG::GNFA(*regexp); 372 } 373 | /* empty */ { $$ = new KDevPG::GNFA(KDevPG::GNFA::emptyWord()); } 374 ; 375 376aregexp 377 : aregexp '|' aregexp1 { $$ = new KDevPG::GNFA(*$1 |= *$3); delete $1; delete $3; } 378 | aregexp1 { $$ = $1; } 379 ; 380 381aregexp1 382 : aregexp1 '&' aregexp2 { $$ = new KDevPG::GNFA(*$1 &= *$3); delete $1; delete $3; } 383 | aregexp2 { $$ = $1; } 384 ; 385 386aregexp2 387 : aregexp3 '^' aregexp2 { $$ = new KDevPG::GNFA(*$1 ^= *$3); delete $1; delete $3; } 388 | aregexp3 { $$ = $1; } 389 ; 390 391aregexp3 392 : '~' aregexp3 { $$ = new KDevPG::GNFA($2->negate()); delete $2; } 393 | '?' aregexp3 { $$ = new KDevPG::GNFA(*$2 |= KDevPG::GNFA::emptyWord()); delete $2; } 394 | aregexp4 { $$ = $1; } 395 ; 396 397aregexp4 398 : aregexp4 aregexp5 { $$ = new KDevPG::GNFA(*$1 |= *$2); delete $1; delete $2; } 399 | aregexp5 400 ; 401 402aregexp5 403 : aregexp5 '@' aregexp6 { $$ = new KDevPG::GNFA(*$1); KDevPG::GNFA *tmp = new KDevPG::GNFA(*$3 <<= *$1); **tmp; *$$ <<= *tmp; delete tmp; delete $1; delete $3; } 404 | aregexp6 { $$ = $1; } 405 ; 406 407aregexp6 408 : aregexp6 '*' { $$ = new KDevPG::GNFA(**$1); delete $1; } 409 | aregexp6 '+' { $$ = new KDevPG::GNFA(*$1); **$$; *$$ <<= *$1; delete $1; } 410 | aregexp7 { $$ = $1; } 411 ; 412 413aregexp7 414 : '(' regexp ')' { $$ = new KDevPG::GNFA(*$2); delete $2; } 415 | '[' aregexp ']' { $$ = $2; } 416 | '.' { $$ = new KDevPG::GNFA(KDevPG::GNFA::anyChar()); } 417 | T_STRING { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); } 418 | T_RANGE { 419 quint32 begin, end; 420 QString str = KDevPG::unescaped(QByteArray($1)); 421 assert(str.size() >= 3 && str.size() <= 5); 422 if(str[1] == '-') 423 { 424 begin = str[0].unicode(); 425 if(str.size() == 3) 426 end = str[2].unicode(); 427 else 428 end = QChar::surrogateToUcs4(str[2], str[3]); 429 } 430 else 431 { 432 begin = QChar::surrogateToUcs4(str[0], str[1]); 433 assert(str[2] == '-'); 434 if(str.size() == 4) 435 end = str[3].unicode(); 436 else 437 end = QChar::surrogateToUcs4(str[3], str[4]); 438 } 439 $$ = new KDevPG::GNFA(KDevPG::GNFA::range(begin, end+1)); 440 } 441 | T_UNQUOTED_STRING { $$ = new KDevPG::GNFA(KDevPG::GNFA::collection(KDevPG::unescaped(QByteArray($1)))); } 442 | T_NAMED_REGEXP { 443 if(!KDevPG::globalSystem.regexpById.contains($1)) 444 { 445 KDevPG::checkOut << "** ERROR: no named regexp " << $1 << endl; 446 exit(-1); 447 } 448 KDevPG::GNFA *regexp = KDevPG::globalSystem.regexpById[$1]; 449 if(!KDevPG::globalSystem.dfaForNfa.contains(regexp)) 450 { 451 KDevPG::globalSystem.dfaForNfa[regexp] = new KDevPG::GDFA(regexp->dfa()); 452 KDevPG::globalSystem.dfaForNfa[regexp]->minimize(); 453 *regexp = KDevPG::globalSystem.dfaForNfa[regexp]->nfa(); 454 } 455 $$ = new KDevPG::GNFA(*regexp); 456 } 457 | /* empty */ { $$ = new KDevPG::GNFA(KDevPG::GNFA::emptyWord()); } 458 ; 459 460 461member_declaration_rest 462 : '(' T_PUBLIC T_DECLARATION ')' T_CODE 463 { $$ = KDevPG::member(KDevPG::Settings::MemberItem::PublicDeclaration, $5); } 464 | '(' T_PROTECTED T_DECLARATION ')' T_CODE 465 { $$ = KDevPG::member(KDevPG::Settings::MemberItem::ProtectedDeclaration, $5); } 466 | '(' T_PRIVATE T_DECLARATION ')' T_CODE 467 { $$ = KDevPG::member(KDevPG::Settings::MemberItem::PrivateDeclaration, $5); } 468 | '(' T_CONSTRUCTOR ')' T_CODE 469 { $$ = KDevPG::member(KDevPG::Settings::MemberItem::ConstructorCode, $4); } 470 | '(' T_DESTRUCTOR ')' T_CODE 471 { $$ = KDevPG::member(KDevPG::Settings::MemberItem::DestructorCode, $4); } 472 ; 473 474declared_tokens 475 : T_TERMINAL { KDevPG::globalSystem.pushTerminal($1,$1); } 476 | T_TERMINAL '(' T_STRING ')' { KDevPG::globalSystem.pushTerminal($1,$3); } 477 | declared_tokens ',' T_TERMINAL { KDevPG::globalSystem.pushTerminal($3,$3); } 478 | declared_tokens ',' T_TERMINAL '(' T_STRING ')' 479 { KDevPG::globalSystem.pushTerminal($3,$5); } 480 ; 481 482rules 483 : /* empty */ 484 | rules item ';' { KDevPG::globalSystem.pushRule($2); } 485 ; 486 487primary_item 488 : '0' { $$ = KDevPG::globalSystem.zero(); } 489 | '(' option_item ')' { $$ = $2; } 490 | try_item { $$ = $1; } 491 | primary_atom { $$ = $1; } 492 | T_INLINE T_IDENTIFIER { $$ = KDevPG::inlinedNonTerminal(KDevPG::globalSystem.pushSymbol($2)); } 493 | name scope primary_atom { $$ = KDevPG::annotation($1, $3, false, $2); } 494 | '#' name scope primary_atom { $$ = KDevPG::annotation($2, $4, true, $3); } 495 ; 496 497primary_atom 498 : T_IDENTIFIER rule_arguments_opt { $$ = KDevPG::nonTerminal(KDevPG::globalSystem.pushSymbol($1), $2); } 499 | T_TERMINAL { $$ = KDevPG::globalSystem.terminal($1); } 500 ; 501 502try_item 503 : T_TRY_RECOVER '(' option_item ')' 504 { 505 KDevPG::globalSystem.needStateManagement = true; 506 $$ = KDevPG::tryCatch($3, 0); 507 } 508 | T_TRY_ROLLBACK '(' option_item ')' T_CATCH '(' option_item ')' 509 { 510 KDevPG::globalSystem.needStateManagement = true; 511 $$ = KDevPG::tryCatch($3, $7); 512 } 513 514rule_arguments_opt 515 : /* empty */ { $$ = const_cast<char*>(""); } 516 | T_RULE_ARGUMENTS { $$ = $1; } 517 ; 518 519name 520 : T_IDENTIFIER { $$ = $1; } 521/* | T_IDENTIFIER '.' T_IDENTIFIER 522 { 523 $$ = $3; 524 fprintf(stderr, "** WARNING support for scoped name" 525 " ``%s.%s'' not implemented\n", $1, $3); 526 }*/ 527 ; 528 529scope 530 : '=' { $$ = KDevPG::Model::VariableDeclarationItem::StorageAstMember; } 531 | ':' { $$ = KDevPG::Model::VariableDeclarationItem::StorageTemporary; } 532 ; 533 534unary_item 535 : primary_item '+' { $$ = KDevPG::plus($1); } 536 | primary_item '*' { $$ = KDevPG::star($1); } 537 | primary_item { $$ = $1; } 538 | '?' primary_item { $$ = KDevPG::alternative($2, KDevPG::globalSystem.zero()); } 539 ; 540 541postfix_item 542 : unary_item { $$ = $1; } 543 | postfix_item '@' primary_item 544 { 545 KDevPG::CloneTree cl; 546 $$ = KDevPG::cons($1, KDevPG::star(KDevPG::cons(cl.clone($3), cl.clone($1)))); 547 } 548 | postfix_item T_CODE { $$ = KDevPG::action($1, $2); } 549 | T_CODE { $$ = KDevPG::action(0, $1); } 550 ; 551 552item_sequence 553 : postfix_item { $$ = $1; } 554 | item_sequence postfix_item { $$ = KDevPG::cons($1, $2); } 555 ; 556 557conditional_item 558 : item_sequence { $$ = $1; } 559 | '?' T_CODE item_sequence { $$ = KDevPG::condition($2, $3); } 560 ; 561 562option_item 563 : conditional_item { $$ = $1; } 564 | option_item '|' conditional_item { $$ = KDevPG::alternative($1, $3); } 565 ; 566 567item 568 : option_item T_ARROW T_IDENTIFIER T_CODE '[' variableDeclarations ']' 569 { 570 $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3), 571 (KDevPG::Model::VariableDeclarationItem*) $6, $4); 572 } 573 | option_item T_ARROW T_IDENTIFIER '[' variableDeclarations ']' code_opt 574 { 575 $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3), 576 (KDevPG::Model::VariableDeclarationItem*) $5, $7); 577 } 578 | option_item T_ARROW T_IDENTIFIER code_opt 579 { $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3), 0, $4); } 580 | { if(KDevPG::globalSystem.generateAst == false) 581 { 582 qFatal("Operator-expression-parsing is not yet supported with --no-ast!"); 583 exit(-1); 584 } 585 operatorNode = KDevPG::createNode<KDevPG::Model::OperatorItem>(); 586 } operatorRule { KDevPG::globalSystem.needOperatorStack = true; $$ = $2; } 587 ; 588 589code_opt 590 : /* empty */ { $$ = const_cast<char*>(""); } 591 | T_CODE { $$ = $1; } 592 ; 593 594 595operatorDeclarations 596 : operatorDeclaration operatorDeclarations 597 | /* empty */ { ; } 598 ; 599 600operatorRule 601 : T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER '[' variableDeclarations ']' code_opt 602 { 603 operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2; 604 operatorNode->mName = $5; 605 if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName)) 606 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast"; 607 $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), (KDevPG::Model::VariableDeclarationItem*)$7, $9); 608 } 609 | T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER T_CODE '[' variableDeclarations ']' 610 { 611 operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2; 612 operatorNode->mName = $5; 613 if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName)) 614 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast"; 615 $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), (KDevPG::Model::VariableDeclarationItem*)$8, $6); 616 } 617 | T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER code_opt 618 { 619 operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2; 620 operatorNode->mName = $5; 621 if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName)) 622 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast"; 623 $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), 0, $6); 624 } 625 ; 626 627operatorDeclaration 628 : T_BIN operator priority assoc { operatorNode->pushBin(*$2, $4, $3); free($2); } 629 | T_TERN operator operator priority assoc { operatorNode->pushTern(*$2, *$3, $5, $4); free($2); free($3); } 630 | T_PRE operator priority { operatorNode->pushPre(*$2, $3); free($2); } 631 | T_POST operator priority { operatorNode->pushPost(*$2, "0", $3); free($2); free($3); } 632 | T_POST operator priority assoc { operatorNode->pushPost(*$2, $4, $3); free($2); } 633 | T_PAREN operator operator { operatorNode->pushParen(*$2, *$3); free($2); free($3); } 634 ; 635 636priority 637 : '0' { $$ = (char*)"0"; } 638 | T_NUMBER { $$ = $1; } 639 | T_PRIORITY T_CODE { $$ = $2; } 640 ; 641 642assoc 643 : T_LEFT_ASSOC { $$ = (char*)"1"; } 644 | T_RIGHT_ASSOC { $$ = (char*)"0"; } 645 | T_IS_LEFT_ASSOC T_CODE { uint yyleng = strlen($2); 646 char *tmp = (char*)calloc(yyleng+7, sizeof(char)); 647 tmp[0] = '('; 648 strcpy(tmp+1, $2); 649 strcpy(tmp+yyleng+6-6+1, "?1:0)"); 650 $$ = tmp; 651 } 652 | T_IS_RIGHT_ASSOC T_CODE { uint yyleng = strlen($2); 653 char *tmp = (char*)calloc(yyleng+7, sizeof(char)); 654 tmp[0] = '('; 655 strcpy(tmp+1, $2); 656 strcpy(tmp+yyleng+6-6+1, "?0:1)"); 657 $$ = tmp; 658 } 659 ; 660 661operator 662 : '?' T_CODE T_TERMINAL T_CODE { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($3), $2, $4); } 663 | '?' T_CODE T_TERMINAL { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($3), $2, ""); } 664 | T_TERMINAL T_CODE { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($1), "", $2); } 665 | T_TERMINAL { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($1), "", ""); } 666 ; 667 668variableDeclarations 669 : variableDeclaration { $$ = $1; } 670 | variableDeclarations variableDeclaration 671 { 672 KDevPG::Model::VariableDeclarationItem *last = (KDevPG::Model::VariableDeclarationItem*) $1; 673 while (last->mNext != 0) { 674 last = last->mNext; 675 } 676 last->mNext = (KDevPG::Model::VariableDeclarationItem*) $2; 677 $$ = $1; 678 } 679 ; 680 681variableDeclaration 682 : declarationType_opt storageType variableType T_IDENTIFIER ':' T_IDENTIFIER 683 { $$ = KDevPG::variableDeclaration($1, $2, $3, false, $4, $6); } 684 | declarationType_opt storageType T_TOKEN T_IDENTIFIER ';' 685 { $$ = KDevPG::variableDeclaration($1, $2, KDevPG::Model::VariableDeclarationItem::TypeToken, false, $4, ""); } 686 | declarationType_opt storageType variableType '#' T_IDENTIFIER ':' T_IDENTIFIER 687 { $$ = KDevPG::variableDeclaration($1, $2, $3, true, $5, $7); } 688 | declarationType_opt storageType T_TOKEN '#' T_IDENTIFIER ';' 689 { $$ = KDevPG::variableDeclaration($1, $2, KDevPG::Model::VariableDeclarationItem::TypeToken, true, $5, ""); } 690 ; 691 692declarationType_opt 693 : /* empty */ { $$ = KDevPG::Model::VariableDeclarationItem::DeclarationLocal; } 694 | T_ARGUMENT { $$ = KDevPG::Model::VariableDeclarationItem::DeclarationArgument; } 695 ; 696 697storageType 698 : T_MEMBER { $$ = KDevPG::Model::VariableDeclarationItem::StorageAstMember; } 699 | T_TEMPORARY { $$ = KDevPG::Model::VariableDeclarationItem::StorageTemporary; } 700 ; 701 702variableType 703 : T_NODE { $$ = KDevPG::Model::VariableDeclarationItem::TypeNode; } 704 | T_VARIABLE { $$ = KDevPG::Model::VariableDeclarationItem::TypeVariable; } 705 ; 706 707%% 708