Warning, /kdevelop/kdevelop-pg-qt/kdev-pg/kdev-pg-parser.yy is written in an unsupported language. File is not indexed.

0001 
0002 %{
0003 /* This file is part of kdev-pg-qt
0004    Copyright (C) 2005 Roberto Raggi <roberto@kdevelop.org>
0005    Copyright (C) 2006 Jakob Petsovits <jpetso@gmx.at>
0006 
0007    This library is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU Library General Public
0009    License as published by the Free Software Foundation; either
0010    version 2 of the License, or (at your option) any later version.
0011 
0012    This library is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    Library General Public License for more details.
0016 
0017    You should have received a copy of the GNU Library General Public License
0018    along with this library; see the file COPYING.LIB.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020    Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #include "kdev-pg.h"
0024 #include "kdev-pg-clone-tree.h"
0025 #include "kdev-pg-regexp.h"
0026 #include "kdev-pg-unicode-loader.h"
0027 #include "kdev-pg-checker.h"
0028 
0029 #include <QFile>
0030 #include <cassert>
0031 
0032 extern int yylex();
0033 extern void yyerror(const char* msg);
0034 extern int yyLine;
0035 
0036 QString lexerEnv;
0037 
0038 namespace KDevPG
0039 {
0040     extern QFile file;
0041     extern QTextStream checkOut;
0042 }
0043 
0044 KDevPG::Model::OperatorItem *operatorNode = nullptr;
0045 QString r;
0046 
0047 %}
0048 
0049 %union {
0050     KDevPG::Model::Node *item;
0051     char* str;
0052     KDevPG::Model::VariableDeclarationItem::DeclarationType declarationType;
0053     KDevPG::Model::VariableDeclarationItem::StorageType     storageType;
0054     KDevPG::Model::VariableDeclarationItem::VariableType    variableType;
0055     KDevPG::Model::Operator                                *operatorInformation;
0056     KDevPG::GNFA                                           *nfa;
0057 }
0058 
0059 %token T_IDENTIFIER T_ARROW T_TERMINAL T_CODE T_STRING T_UNQUOTED_STRING T_NUMBER ';'
0060 %token T_TOKEN_DECLARATION T_TOKEN_STREAM_DECLARATION T_NAMESPACE_DECLARATION
0061 %token T_PARSERCLASS_DECLARATION T_LEXERCLASS_DECLARATION
0062 %token T_PUBLIC T_PRIVATE T_PROTECTED T_DECLARATION T_BITS
0063 %token T_CONSTRUCTOR T_DESTRUCTOR T_TRY_RECOVER T_TRY_ROLLBACK T_CATCH
0064 %token T_RULE_ARGUMENTS T_MEMBER T_TEMPORARY T_ARGUMENT T_EXPORT_MACRO
0065 %token T_NODE T_NODE_SEQUENCE T_TOKEN T_VARIABLE T_EXPORT_MACRO_HEADER
0066 %token T_AST_DECLARATION 
0067 %token T_PARSER_DECLARATION_HEADER T_PARSER_BITS_HEADER T_AST_HEADER
0068 %token T_LEXER_DECLARATION_HEADER T_LEXER_BITS_HEADER
0069 %token T_PARSER_BASE T_AST_BASE T_LEXER_BASE
0070 %token T_BIN T_PRE T_POST T_TERN
0071 %token T_LOPR T_ROPR
0072 %token T_LEFT_ASSOC T_RIGHT_ASSOC T_IS_LEFT_ASSOC T_IS_RIGHT_ASSOC T_PRIORITY
0073 %token T_PAREN
0074 %token T_INLINE
0075 %token T_LEXER T_INPUT_STREAM T_INPUT_ENCODING T_TABLE_LEXER T_SEQUENCE_LEXER
0076 %token T_NAMED_REGEXP T_CONTINUE T_RANGE T_FAIL T_LOOKAHEAD T_BARRIER
0077 %token T_ENTER_RULE_SET T_LEAVE_RULE_SET
0078 
0079 %type<str> T_IDENTIFIER T_TERMINAL T_CODE T_STRING T_UNQUOTED_STRING T_RULE_ARGUMENTS T_NUMBER T_NAMED_REGEXP T_RANGE
0080 %type<str> name code_opt rule_arguments_opt priority assoc opt_lexer_action
0081 %type<item> item primary_item try_item primary_atom unary_item
0082 %type<item> postfix_item option_item item_sequence conditional_item
0083 %type<item> member_declaration_rest variableDeclarations variableDeclaration operatorRule
0084 %type<declarationType> declarationType_opt
0085 %type<storageType>     scope storageType
0086 %type<variableType>    variableType
0087 /* %type<void> operatorDeclaration operatorDeclarations operatorRule */
0088 %type<operatorInformation> operator
0089 %type<nfa> regexp regexp1 regexp2 regexp3 regexp4 regexp5 regexp6 regexp7 aregexp aregexp1 aregexp2 aregexp3 aregexp4 aregexp5 aregexp6 aregexp7
0090 
0091 %%
0092 
0093 system
0094     : code_opt { KDevPG::globalSystem.decl = $1; }
0095       declarations
0096       rules
0097       code_opt { KDevPG::globalSystem.bits += $5; }
0098     ;
0099 
0100 declarations
0101     : declaration
0102     | declarations declaration
0103     ;
0104 
0105 declaration
0106     : T_PARSERCLASS_DECLARATION member_declaration_rest
0107         { KDevPG::globalSystem.pushParserClassMember($2); }
0108     | T_PARSERCLASS_DECLARATION '(' T_BITS ')' T_CODE
0109         { KDevPG::globalSystem.bits += $5; }
0110     | T_LEXERCLASS_DECLARATION member_declaration_rest
0111         { KDevPG::globalSystem.pushLexerClassMember($2); }
0112     | T_LEXERCLASS_DECLARATION '(' T_BITS ')' T_CODE
0113         { KDevPG::globalSystem.lexerBits += $5; }
0114     | T_TOKEN_DECLARATION declared_tokens ';'
0115     | T_TABLE_LEXER
0116       { if(KDevPG::globalSystem.hasLexer)
0117         { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%table_lexer) before any lexer rules"; exit(-1); }
0118         switch(KDevPG::GDFA::type)
0119         {
0120           case KDevPG::SAscii: KDevPG::GDFA::type = KDevPG::TAscii; break;
0121           case KDevPG::SLatin1: KDevPG::GDFA::type = KDevPG::TLatin1; break;
0122           case KDevPG::SUtf8: KDevPG::GDFA::type = KDevPG::TUtf8; break;
0123           case KDevPG::SUcs2: KDevPG::GDFA::type = KDevPG::TUcs2; break;
0124           case KDevPG::SUtf16: KDevPG::GDFA::type = KDevPG::TUtf16; break;
0125 /*           case KDevPG::SUcs4: KDevPG::GDFA::type = KDevPG::TUcs4; break; */
0126           default: /* empty */;
0127         }
0128       }
0129     | T_SEQUENCE_LEXER
0130       { if(KDevPG::globalSystem.hasLexer)
0131       { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%sequence_lexer) before any lexer rules"; exit(-1); }
0132       switch(KDevPG::GDFA::type)
0133       {
0134         case KDevPG::TAscii: KDevPG::GDFA::type = KDevPG::SAscii; break;
0135         case KDevPG::TLatin1: KDevPG::GDFA::type = KDevPG::SLatin1; break;
0136         case KDevPG::TUtf8: KDevPG::GDFA::type = KDevPG::SUtf8; break;
0137         case KDevPG::TUcs2: KDevPG::GDFA::type = KDevPG::SUcs2; break;
0138         case KDevPG::TUtf16: KDevPG::GDFA::type = KDevPG::SUtf16; break;
0139 /*         case KDevPG::TUcs4: KDevPG::GDFA::type = KDevPG::SUcs4; break; */
0140         default: /* empty */;
0141       }
0142       }
0143     | T_INPUT_ENCODING T_STRING
0144       {
0145         if(KDevPG::globalSystem.hasLexer)
0146         { KDevPG::checkOut << "** ERROR you have to specify the lexer-type (%sequence_lexer) before any lexer rules"; exit(-1); }
0147         int base = (KDevPG::GDFA::type / 4) * 4; // warning: magic constant: number of different codecs
0148         QString str = $2;
0149         str = str.toLower();
0150         str.replace('-', "");
0151         if(str == "ascii")
0152           /* base += 0*/;
0153         else if(str == "latin1")
0154           base += 1;
0155         else if(str == "utf8")
0156           base += 2;
0157         else if(str == "ucs2")
0158           base += 3;
0159         else if(str == "utf16")
0160           base += 4;
0161         else if(str == "ucs4" || str == "utf32")
0162           base += 5;
0163         else
0164         {
0165           KDevPG::checkOut << "** ERROR unknown codec  ``" << $2 << "''" << Qt::endl;
0166           exit(-1);
0167         }
0168         KDevPG::GDFA::type = KDevPG::AutomatonType(base);
0169       }
0170     | T_TOKEN_STREAM_DECLARATION T_IDENTIFIER ';'
0171         { KDevPG::globalSystem.tokenStream = $2;           }
0172     | T_EXPORT_MACRO T_STRING
0173         { KDevPG::globalSystem.exportMacro = $2;           }
0174     | T_EXPORT_MACRO_HEADER T_STRING
0175         { KDevPG::globalSystem.exportMacroHeader = $2;     }
0176     | T_NAMESPACE_DECLARATION T_CODE
0177         { KDevPG::globalSystem.namespaceCode = $2;         }
0178     | T_AST_DECLARATION T_CODE
0179         { KDevPG::globalSystem.astCode = $2;               }
0180     | T_PARSER_DECLARATION_HEADER T_STRING
0181         { KDevPG::globalSystem.pushParserDeclarationHeader($2); }
0182     | T_PARSER_BITS_HEADER T_STRING
0183         { KDevPG::globalSystem.pushParserBitsHeader($2); }
0184     | T_AST_HEADER T_STRING
0185         { KDevPG::globalSystem.pushAstHeader($2); }
0186     | T_LEXER_DECLARATION_HEADER T_STRING
0187         { KDevPG::globalSystem.pushLexerDeclarationHeader($2); }
0188     | T_INPUT_STREAM T_STRING
0189         { KDevPG::globalSystem.inputStream = $2; }
0190     | T_LEXER_BITS_HEADER T_STRING
0191         { KDevPG::globalSystem.pushLexerBitsHeader($2); }
0192     | T_AST_BASE T_IDENTIFIER T_STRING
0193         { KDevPG::globalSystem.astBaseClasses[$2] = $3; }
0194     | T_PARSER_BASE T_STRING
0195         { KDevPG::globalSystem.parserBaseClass = $2; }
0196     | T_LEXER_BASE T_STRING
0197         { KDevPG::globalSystem.lexerBaseClass = $2; }
0198     | 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 ';'
0199     | 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 ';'
0200     ;
0201 
0202 lexer_declaration_rest
0203     : regexp T_ARROW T_IDENTIFIER ';'
0204             { KDevPG::globalSystem.regexpById[$3] = $1;
0205             } lexer_declaration_rest
0206     | regexp code_opt opt_lexer_action ';'
0207             {
0208               if($1->acceptsEpsilon())
0209                 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << Qt::endl;
0210               else if($1->isEmpty())
0211                 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << Qt::endl;
0212               QString s = QString($2) + QString(r);
0213               KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1);
0214               KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s);
0215             } lexer_declaration_rest
0216     | regexp T_LOOKAHEAD '(' regexp ')' code_opt opt_lexer_action ';'
0217             {
0218               if($1->acceptsEpsilon())
0219                 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << Qt::endl;
0220               else if($1->isEmpty())
0221                 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << Qt::endl;
0222               bool ignore = false;
0223               auto minLen = $4->minLength(), maxLen = $4->maxLength();
0224               if(minLen == 0)
0225               {
0226                 KDevPG::checkOut << "** WARNING Lexer rule specifying epsilon-lookahead at line " << yyLine << ", ignore the lookahead." << Qt::endl;
0227                 ignore = true;
0228               }
0229               else if(minLen != maxLen)
0230               {
0231                 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." << Qt::endl;
0232                 ignore = true;
0233               }
0234               if(ignore)
0235               {
0236                 QString s = QString($6) + QString(r);
0237                 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1);
0238                 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s);
0239               }
0240               else
0241               {
0242                 QString s = "Iterator::plain() -= " + QString::number(minLen) + "; " + QString($6) + QString(r);
0243                 *$1 <<= *$4;
0244                 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1);
0245                 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s);
0246               }
0247             } lexer_declaration_rest
0248     | regexp T_BARRIER '(' regexp ')' code_opt opt_lexer_action ';'
0249             {
0250               if($1->acceptsEpsilon())
0251                 KDevPG::checkOut << "** WARNING Lexer rule accepting the empty word at line " << yyLine << Qt::endl;
0252               else if($1->isEmpty())
0253                 KDevPG::checkOut << "** WARNING Lexer rule not accepting anything at line " << yyLine << Qt::endl;
0254               bool ignore = false;
0255               auto minLen = $4->minLength(), maxLen = $4->maxLength();
0256               if(minLen == 0)
0257               {
0258                 KDevPG::checkOut << "** WARNING Lexer rule specifying epsilon-barrier at line " << yyLine << ", ignore the barrier." << Qt::endl;
0259                 ignore = true;
0260               }
0261               else if(minLen != maxLen)
0262               {
0263                 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." << Qt::endl;
0264                 ignore = true;
0265               }
0266               if(ignore)
0267               {
0268                 QString s = QString($6) + QString(r);
0269                 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1);
0270                 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s);
0271               }
0272               else
0273               {
0274                 KDevPG::GNFA exclude = KDevPG::GNFA::anything();
0275                 exclude <<= *$4;
0276                 exclude <<= KDevPG::GNFA::anything();
0277                 KDevPG::GNFA *staying = new KDevPG::GNFA(*$1);
0278                 *staying ^= exclude;
0279                 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back(staying);
0280                 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(QString($6) + QString(r));
0281                 // barrier should not get read partially
0282                 exclude <<= KDevPG::GNFA::anyChar();
0283                 *$1 <<= *$4;
0284                 *$1 ^= exclude;
0285                 QString s = "Iterator::plain() -= " + QString::number(minLen) + "; " + QString($6) + QString(r);
0286                 KDevPG::globalSystem.lexerEnvs[lexerEnv].push_back($1);
0287                 KDevPG::globalSystem.lexerActions[lexerEnv].push_back(s);
0288               }
0289             } lexer_declaration_rest
0290     | T_FAIL T_CODE
0291             {
0292               KDevPG::globalSystem.lexerActions[lexerEnv][0] = QString($2);
0293             } lexer_declaration_rest
0294     | T_ENTER_RULE_SET T_CODE
0295             {
0296               KDevPG::globalSystem.enteringCode[lexerEnv] = QString($2);
0297             } lexer_declaration_rest
0298     | T_LEAVE_RULE_SET T_CODE
0299             {
0300               KDevPG::globalSystem.leavingCode[lexerEnv] = QString($2);
0301             } lexer_declaration_rest
0302     | /* empty */
0303     ;
0304 
0305 opt_lexer_action
0306     : T_TERMINAL {
0307         r = "\nlxRETURN(" + QString($1) + ")\n";
0308       }
0309     | T_CONTINUE {
0310         r = "\nlxCONTINUE;\n";
0311       }
0312     | /* empty */ { r = "\nlxSKIP\n"; }
0313     ;
0314 
0315 regexp
0316     : regexp '|' regexp1    { $$ = new KDevPG::GNFA(*$1 |= *$3); delete $1; delete $3; }
0317     | regexp1               { $$ = $1; }
0318     ;
0319 
0320 regexp1
0321     : regexp1 '&' regexp2   { $$ = new KDevPG::GNFA(*$1 &= *$3); delete $1; delete $3; }
0322     | regexp2               { $$ = $1; }
0323     ;
0324 
0325 regexp2
0326     : regexp3 '^' regexp2   { $$ = new KDevPG::GNFA(*$1 ^= *$3); delete $1; delete $3; }
0327     | regexp3               { $$ = $1; }
0328     ;
0329 
0330 regexp3
0331     : '~' regexp3           { $$ = new KDevPG::GNFA($2->negate()); delete $2; }
0332     | '?' regexp3           { $$ = new KDevPG::GNFA(*$2 |= KDevPG::GNFA::emptyWord()); delete $2; }
0333     | regexp4               { $$ = $1; }
0334     ;
0335 
0336 regexp4
0337     : regexp4 regexp5       { $$ = new KDevPG::GNFA(*$1 <<= *$2); delete $1; delete $2; }
0338     | regexp5               { $$ = $1; }
0339     ;
0340 
0341 regexp5
0342     : regexp5 '@' regexp6   { $$ = new KDevPG::GNFA(*$1); KDevPG::GNFA *tmp = new KDevPG::GNFA(*$3 <<= *$1); **tmp; *$$ <<= *tmp; delete tmp; delete $1; delete $3; }
0343     | regexp6               { $$ = $1; }
0344     ;
0345     
0346 regexp6
0347     : regexp6 '*'           { $$ = new KDevPG::GNFA(**$1); delete $1; }
0348     | regexp6 '+'           { $$ = new KDevPG::GNFA(*$1); **$$; *$$ <<= *$1; delete $1; }
0349     | regexp7               { $$ = $1; }
0350     ;
0351 
0352 regexp7
0353     : '(' regexp ')'        { $$ = new KDevPG::GNFA(*$2); delete $2; }
0354     | '[' aregexp ']'       { $$ = $2; }
0355     | '.'                   { $$ = new KDevPG::GNFA(KDevPG::GNFA::anyChar()); }
0356     | T_STRING              { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); }
0357     | T_UNQUOTED_STRING     { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); }
0358     | T_NAMED_REGEXP        {
0359                               if(!KDevPG::globalSystem.regexpById.contains($1))
0360                               {
0361                                 KDevPG::checkOut << "** ERROR: no named regexp " << $1 << Qt::endl;
0362                                 exit(-1);
0363                               }
0364                               KDevPG::GNFA *regexp = KDevPG::globalSystem.regexpById[$1];
0365                               if(!KDevPG::globalSystem.dfaForNfa.contains(regexp))
0366                               {
0367                                 KDevPG::globalSystem.dfaForNfa[regexp] = new KDevPG::GDFA(regexp->dfa());
0368                                 KDevPG::globalSystem.dfaForNfa[regexp]->minimize();
0369                                 *regexp = KDevPG::globalSystem.dfaForNfa[regexp]->nfa();
0370                               }
0371                               $$ = new KDevPG::GNFA(*regexp);
0372                             }
0373     | /* empty */           { $$ = new KDevPG::GNFA(KDevPG::GNFA::emptyWord()); }
0374     ;
0375 
0376 aregexp
0377     : aregexp '|' aregexp1  { $$ = new KDevPG::GNFA(*$1 |= *$3); delete $1; delete $3; }
0378     | aregexp1              { $$ = $1; }
0379     ;
0380 
0381 aregexp1
0382     : aregexp1 '&' aregexp2 { $$ = new KDevPG::GNFA(*$1 &= *$3); delete $1; delete $3; }
0383     | aregexp2              { $$ = $1; }
0384     ;
0385 
0386 aregexp2
0387     : aregexp3 '^' aregexp2 { $$ = new KDevPG::GNFA(*$1 ^= *$3); delete $1; delete $3; }
0388     | aregexp3              { $$ = $1; }
0389     ;
0390 
0391 aregexp3
0392     : '~' aregexp3          { $$ = new KDevPG::GNFA($2->negate()); delete $2; }
0393     | '?' aregexp3          { $$ = new KDevPG::GNFA(*$2 |= KDevPG::GNFA::emptyWord()); delete $2; }
0394     | aregexp4              { $$ = $1; }
0395     ;
0396 
0397 aregexp4
0398     : aregexp4 aregexp5     { $$ = new KDevPG::GNFA(*$1 |= *$2); delete $1; delete $2; }
0399     | aregexp5
0400     ;
0401 
0402 aregexp5
0403     : aregexp5 '@' aregexp6 { $$ = new KDevPG::GNFA(*$1); KDevPG::GNFA *tmp = new KDevPG::GNFA(*$3 <<= *$1); **tmp; *$$ <<= *tmp; delete tmp; delete $1; delete $3; }
0404     | aregexp6              { $$ = $1; }
0405     ;
0406     
0407 aregexp6
0408     : aregexp6 '*'          { $$ = new KDevPG::GNFA(**$1); delete $1; }
0409     | aregexp6 '+'          { $$ = new KDevPG::GNFA(*$1); **$$; *$$ <<= *$1; delete $1; }
0410     | aregexp7              { $$ = $1; }
0411     ;
0412 
0413 aregexp7
0414     : '(' regexp ')'        { $$ = new KDevPG::GNFA(*$2); delete $2; }
0415     | '[' aregexp ']'       { $$ = $2; }
0416     | '.'                   { $$ = new KDevPG::GNFA(KDevPG::GNFA::anyChar()); }
0417     | T_STRING              { $$ = new KDevPG::GNFA(KDevPG::GNFA::word(KDevPG::unescaped(QByteArray($1)))); }
0418     | T_RANGE               {
0419       quint32 begin, end;
0420       QString str = KDevPG::unescaped(QByteArray($1));
0421       assert(str.size() >= 3 && str.size() <= 5);
0422       if(str[1] == '-')
0423       {
0424         begin = str[0].unicode();
0425         if(str.size() == 3)
0426           end = str[2].unicode();
0427         else
0428           end = QChar::surrogateToUcs4(str[2], str[3]);
0429       }
0430       else
0431       {
0432         begin = QChar::surrogateToUcs4(str[0], str[1]);
0433         assert(str[2] == '-');
0434         if(str.size() == 4)
0435           end = str[3].unicode();
0436         else
0437           end = QChar::surrogateToUcs4(str[3], str[4]);
0438       }
0439       $$ = new KDevPG::GNFA(KDevPG::GNFA::range(begin, end+1));
0440     }
0441     | T_UNQUOTED_STRING     { $$ = new KDevPG::GNFA(KDevPG::GNFA::collection(KDevPG::unescaped(QByteArray($1)))); }
0442     | T_NAMED_REGEXP        {
0443                               if(!KDevPG::globalSystem.regexpById.contains($1))
0444                               {
0445                                 KDevPG::checkOut << "** ERROR: no named regexp " << $1 << Qt::endl;
0446                                 exit(-1);
0447                               }
0448                               KDevPG::GNFA *regexp = KDevPG::globalSystem.regexpById[$1];
0449                               if(!KDevPG::globalSystem.dfaForNfa.contains(regexp))
0450                               {
0451                                 KDevPG::globalSystem.dfaForNfa[regexp] = new KDevPG::GDFA(regexp->dfa());
0452                                 KDevPG::globalSystem.dfaForNfa[regexp]->minimize();
0453                                 *regexp = KDevPG::globalSystem.dfaForNfa[regexp]->nfa();
0454                               }
0455                               $$ = new KDevPG::GNFA(*regexp);
0456                             }
0457     | /* empty */           { $$ = new KDevPG::GNFA(KDevPG::GNFA::emptyWord()); }
0458     ;
0459 
0460 
0461 member_declaration_rest
0462     : '(' T_PUBLIC T_DECLARATION ')' T_CODE
0463         { $$ = KDevPG::member(KDevPG::Settings::MemberItem::PublicDeclaration, $5);    }
0464     | '(' T_PROTECTED T_DECLARATION ')' T_CODE
0465         { $$ = KDevPG::member(KDevPG::Settings::MemberItem::ProtectedDeclaration, $5); }
0466     | '(' T_PRIVATE T_DECLARATION ')' T_CODE
0467         { $$ = KDevPG::member(KDevPG::Settings::MemberItem::PrivateDeclaration, $5);   }
0468     | '(' T_CONSTRUCTOR ')' T_CODE
0469         { $$ = KDevPG::member(KDevPG::Settings::MemberItem::ConstructorCode, $4);      }
0470     | '(' T_DESTRUCTOR ')' T_CODE
0471         { $$ = KDevPG::member(KDevPG::Settings::MemberItem::DestructorCode, $4);       }
0472     ;
0473 
0474 declared_tokens
0475     : T_TERMINAL                        { KDevPG::globalSystem.pushTerminal($1,$1); }
0476     | T_TERMINAL '(' T_STRING ')'       { KDevPG::globalSystem.pushTerminal($1,$3); }
0477     | declared_tokens ',' T_TERMINAL    { KDevPG::globalSystem.pushTerminal($3,$3); }
0478     | declared_tokens ',' T_TERMINAL '(' T_STRING ')'
0479                                         { KDevPG::globalSystem.pushTerminal($3,$5); }
0480     ;
0481 
0482 rules
0483     : /* empty */
0484     | rules item ';'                    { KDevPG::globalSystem.pushRule($2); }
0485     ;
0486 
0487 primary_item
0488     : '0'                               { $$ = KDevPG::globalSystem.zero(); }
0489     | '(' option_item ')'               { $$ = $2; }
0490     | try_item                    { $$ = $1; }
0491     | primary_atom                      { $$ = $1; }
0492     | T_INLINE T_IDENTIFIER              { $$ = KDevPG::inlinedNonTerminal(KDevPG::globalSystem.pushSymbol($2)); }
0493     | name scope primary_atom           { $$ = KDevPG::annotation($1, $3, false, $2); }
0494     | '#' name scope primary_atom       { $$ = KDevPG::annotation($2, $4, true, $3);  }
0495     ;
0496 
0497 primary_atom
0498     : T_IDENTIFIER rule_arguments_opt   { $$ = KDevPG::nonTerminal(KDevPG::globalSystem.pushSymbol($1), $2); }
0499     | T_TERMINAL                        { $$ = KDevPG::globalSystem.terminal($1); }
0500     ;
0501 
0502 try_item
0503     : T_TRY_RECOVER '(' option_item ')'
0504         {
0505           KDevPG::globalSystem.needStateManagement = true;
0506           $$ = KDevPG::tryCatch($3, nullptr);
0507         }
0508     | T_TRY_ROLLBACK '(' option_item ')' T_CATCH '(' option_item ')'
0509         {
0510           KDevPG::globalSystem.needStateManagement = true;
0511           $$ = KDevPG::tryCatch($3, $7);
0512         }
0513 
0514 rule_arguments_opt
0515     : /* empty */                       { $$ = const_cast<char*>(""); }
0516     | T_RULE_ARGUMENTS                  { $$ = $1; }
0517     ;
0518 
0519 name
0520     : T_IDENTIFIER                      { $$ = $1; }
0521 /*    | T_IDENTIFIER '.' T_IDENTIFIER
0522         {
0523           $$ = $3;
0524           fprintf(stderr, "** WARNING support for scoped name"
0525                           " ``%s.%s'' not implemented\n", $1, $3);
0526         }*/
0527     ;
0528 
0529 scope
0530     : '=' { $$ = KDevPG::Model::VariableDeclarationItem::StorageAstMember; }
0531     | ':' { $$ = KDevPG::Model::VariableDeclarationItem::StorageTemporary;  }
0532     ;
0533 
0534 unary_item
0535     : primary_item '+'                  { $$ = KDevPG::plus($1); }
0536     | primary_item '*'                  { $$ = KDevPG::star($1); }
0537     | primary_item                      { $$ = $1; }
0538     | '?' primary_item                   { $$ = KDevPG::alternative($2, KDevPG::globalSystem.zero()); }
0539     ;
0540 
0541 postfix_item
0542     : unary_item                        { $$ = $1; }
0543     | postfix_item '@' primary_item
0544         {
0545           KDevPG::CloneTree cl;
0546           $$ = KDevPG::cons($1, KDevPG::star(KDevPG::cons(cl.clone($3), cl.clone($1))));
0547         }
0548     | postfix_item T_CODE               { $$ = KDevPG::action($1, $2); }
0549     | T_CODE                            { $$ = KDevPG::action(nullptr, $1); }
0550     ;
0551 
0552 item_sequence
0553     : postfix_item                      { $$ = $1; }
0554     | item_sequence postfix_item        { $$ = KDevPG::cons($1, $2); }
0555     ;
0556 
0557 conditional_item
0558     : item_sequence                     { $$ = $1; }
0559     | '?' T_CODE item_sequence          { $$ = KDevPG::condition($2, $3); }
0560     ;
0561 
0562 option_item
0563     : conditional_item                  { $$ = $1; }
0564     | option_item '|' conditional_item  { $$ = KDevPG::alternative($1, $3); }
0565     ;
0566 
0567 item
0568     : option_item T_ARROW T_IDENTIFIER T_CODE '[' variableDeclarations ']'
0569         {
0570           $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3),
0571                           (KDevPG::Model::VariableDeclarationItem*) $6, $4);
0572         }
0573     | option_item T_ARROW T_IDENTIFIER '[' variableDeclarations ']' code_opt
0574         {
0575           $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3),
0576                           (KDevPG::Model::VariableDeclarationItem*) $5, $7);
0577         }
0578     | option_item T_ARROW T_IDENTIFIER code_opt
0579         { $$ = KDevPG::evolve($1, KDevPG::globalSystem.pushSymbol($3), nullptr, $4); }
0580     | { if(KDevPG::globalSystem.generateAst == false)
0581         {
0582           qFatal("Operator-expression-parsing is not yet supported with --no-ast!");
0583           exit(-1);
0584         }
0585         operatorNode = KDevPG::createNode<KDevPG::Model::OperatorItem>();
0586       } operatorRule { KDevPG::globalSystem.needOperatorStack = true; $$ = $2; }
0587     ;
0588 
0589 code_opt
0590     : /* empty */                       { $$ = const_cast<char*>(""); }
0591     | T_CODE                            { $$ = $1; }
0592     ;
0593 
0594 
0595 operatorDeclarations
0596     : operatorDeclaration operatorDeclarations
0597     | /* empty */   { ; }
0598     ;
0599 
0600 operatorRule
0601     : T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER '[' variableDeclarations ']' code_opt
0602             {
0603               operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2;
0604               operatorNode->mName = $5;
0605               if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName))
0606                 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast";
0607               $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), (KDevPG::Model::VariableDeclarationItem*)$7, $9);
0608             }
0609     | T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER T_CODE '[' variableDeclarations ']'
0610             {
0611               operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2;
0612               operatorNode->mName = $5;
0613               if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName))
0614                 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast";
0615               $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), (KDevPG::Model::VariableDeclarationItem*)$8, $6);
0616             }
0617     | T_LOPR primary_atom operatorDeclarations T_ROPR T_IDENTIFIER code_opt
0618             {
0619               operatorNode->mBase = (KDevPG::Model::NonTerminalItem*)$2;
0620               operatorNode->mName = $5;
0621               if(!KDevPG::globalSystem.astBaseClasses.contains(operatorNode->mBase->mSymbol->mName))
0622                 KDevPG::globalSystem.astBaseClasses[operatorNode->mBase->mSymbol->mName] = KDevPG::capitalized(operatorNode->mName) + "Ast";
0623               $$ = KDevPG::evolve(operatorNode, KDevPG::globalSystem.pushSymbol($5), nullptr, $6);
0624             }
0625     ;
0626 
0627 operatorDeclaration
0628     : T_BIN operator priority assoc              { operatorNode->pushBin(*$2, $4, $3); free($2); }
0629     | T_TERN operator operator priority assoc    { operatorNode->pushTern(*$2, *$3, $5, $4); free($2); free($3); }
0630     | T_PRE operator priority                    { operatorNode->pushPre(*$2, $3); free($2); }
0631     | T_POST operator priority                   { operatorNode->pushPost(*$2, "0", $3); free($2); free($3); }
0632     | T_POST operator priority assoc             { operatorNode->pushPost(*$2, $4, $3); free($2); }
0633     | T_PAREN operator operator                  { operatorNode->pushParen(*$2, *$3); free($2); free($3); }
0634     ;
0635     
0636 priority
0637     : '0'                          { $$ = (char*)"0"; }
0638     | T_NUMBER                     { $$ = $1; }
0639     | T_PRIORITY T_CODE            { $$ = $2; }
0640     ;
0641     
0642 assoc
0643     : T_LEFT_ASSOC                 { $$ = (char*)"1"; }
0644     | T_RIGHT_ASSOC                { $$ = (char*)"0"; }
0645     | T_IS_LEFT_ASSOC T_CODE       { uint yyleng = strlen($2);
0646                                      char *tmp = (char*)calloc(yyleng+7, sizeof(char));
0647                                      tmp[0] = '(';
0648                                      strcpy(tmp+1, $2);
0649                                      strcpy(tmp+yyleng+6-6+1, "?1:0)");
0650                                      $$ = tmp;
0651                                    }
0652     | T_IS_RIGHT_ASSOC T_CODE      { uint yyleng = strlen($2);
0653                                      char *tmp = (char*)calloc(yyleng+7, sizeof(char));
0654                                      tmp[0] = '(';
0655                                      strcpy(tmp+1, $2);
0656                                      strcpy(tmp+yyleng+6-6+1, "?0:1)");
0657                                      $$ = tmp;
0658                                    }
0659     ;
0660     
0661 operator
0662     : '?' T_CODE T_TERMINAL T_CODE { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($3), $2, $4); }
0663     | '?' T_CODE T_TERMINAL        { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($3), $2, ""); }
0664     | T_TERMINAL T_CODE            { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($1), "", $2); }
0665     | T_TERMINAL                   { $$ = KDevPG::makeOperator(KDevPG::globalSystem.terminal($1), "", ""); }
0666     ;
0667 
0668 variableDeclarations
0669     : variableDeclaration              { $$ = $1; }
0670     | variableDeclarations variableDeclaration
0671         {
0672           KDevPG::Model::VariableDeclarationItem *last = (KDevPG::Model::VariableDeclarationItem*) $1;
0673           while (last->mNext != nullptr) {
0674             last = last->mNext;
0675           }
0676           last->mNext = (KDevPG::Model::VariableDeclarationItem*) $2;
0677           $$ = $1;
0678         }
0679     ;
0680 
0681 variableDeclaration
0682     : declarationType_opt storageType variableType T_IDENTIFIER ':' T_IDENTIFIER
0683         { $$ = KDevPG::variableDeclaration($1, $2, $3, false, $4, $6); }
0684     | declarationType_opt storageType T_TOKEN       T_IDENTIFIER ';'
0685         { $$ = KDevPG::variableDeclaration($1, $2, KDevPG::Model::VariableDeclarationItem::TypeToken, false, $4, ""); }
0686     | declarationType_opt storageType variableType '#' T_IDENTIFIER ':' T_IDENTIFIER
0687         { $$ = KDevPG::variableDeclaration($1, $2, $3, true, $5, $7); }
0688     | declarationType_opt storageType T_TOKEN       '#' T_IDENTIFIER ';'
0689         { $$ = KDevPG::variableDeclaration($1, $2, KDevPG::Model::VariableDeclarationItem::TypeToken, true, $5, ""); }
0690     ;
0691 
0692 declarationType_opt
0693     : /* empty */       { $$ = KDevPG::Model::VariableDeclarationItem::DeclarationLocal;     }
0694     | T_ARGUMENT        { $$ = KDevPG::Model::VariableDeclarationItem::DeclarationArgument;  }
0695     ;
0696 
0697 storageType
0698     : T_MEMBER          { $$ = KDevPG::Model::VariableDeclarationItem::StorageAstMember;    }
0699     | T_TEMPORARY       { $$ = KDevPG::Model::VariableDeclarationItem::StorageTemporary;     }
0700     ;
0701 
0702 variableType
0703     : T_NODE            { $$ = KDevPG::Model::VariableDeclarationItem::TypeNode;             }
0704     | T_VARIABLE        { $$ = KDevPG::Model::VariableDeclarationItem::TypeVariable;         }
0705     ;
0706 
0707 %%