Warning, /utilities/kregexpeditor/src/qregexpparser.y is written in an unsupported language. File is not indexed.
0001 /*
0002 * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org>
0003 *
0004 * This library is free software; you can redistribute it and/or
0005 * modify it under the terms of the GNU Library General Public
0006 * License version 2 as published by the Free Software Foundation.
0007 *
0008 * This library is distributed in the hope that it will be useful,
0009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0011 * Library General Public License for more details.
0012 *
0013 * You should have received a copy of the GNU Library General Public License
0014 * along with this library; see the file COPYING.LIB. If not, write to
0015 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0016 * Boston, MA 02110-1301, USA.
0017 **/
0018 %{
0019 #ifndef YYENABLE_NLS
0020 # define YYENABLE_NLS 0
0021 #endif
0022
0023 #ifndef YYLTYPE_IS_TRIVIAL
0024 # define YYLTYPE_IS_TRIVIAL 0
0025 #endif
0026
0027 #include <KLocalizedString>
0028 #include <kmessagebox.h>
0029
0030
0031 #include <stdlib.h>
0032
0033 #include "regexp.h"
0034 #include "textregexp.h"
0035 #include "textrangeregexp.h"
0036 #include "repeatregexp.h"
0037 #include "lookaheadregexp.h"
0038 #include "concregexp.h"
0039 #include "altnregexp.h"
0040 #include "positionregexp.h"
0041 #include "dotregexp.h"
0042 #include "compoundregexp.h"
0043 #include "gen_qregexpparser.hh"
0044
0045 #define YY_EXTRA_TYPE struct parse_context *
0046
0047 extern int yylex( YYSTYPE* yylval, yyscan_t scanner );
0048 extern void scannerInit( yyscan_t* scanner, struct parse_context* context, const QString& qstr );
0049 extern void scannerDestroy( yyscan_t scanner );
0050 int yyerror( yyscan_t scanner, struct parse_context* context, const char * );
0051 void setParseResult( RegExp*, struct parse_context* );
0052 RegExp* parseQtRegExp( const QString &qstr, bool* ok );
0053 %}
0054
0055 %code requires {
0056 #include "qregexpparsercommon.h"
0057 #ifndef YY_TYPEDEF_YY_SCANNER_T
0058 #define YY_TYPEDEF_YY_SCANNER_T
0059 typedef void *yyscan_t;
0060 #endif
0061 }
0062
0063 %union {
0064 struct {
0065 int min;
0066 int max;
0067 } range;
0068 int backRef;
0069 RegExp* regexp;
0070 char ch;
0071 }
0072
0073 %token TOK_Dot
0074 %token TOK_Dollar
0075 %token TOK_Carat
0076 %token TOK_MagicLeftParent
0077 %token TOK_PosLookAhead
0078 %token TOK_NegLookAhead
0079 %token TOK_LeftParen
0080 %token TOK_RightParent
0081 %token TOK_Bar
0082 %token TOK_Quantifier
0083 %token TOK_BackRef
0084 %token TOK_CharClass
0085 %token TOK_Char
0086 %token TOK_EscapeChar
0087 %token TOK_PosWordChar
0088 %token TOK_PosNonWordChar
0089
0090 %start regexp
0091
0092 %define api.pure
0093
0094 %param { yyscan_t scanner }
0095 %parse-param { struct parse_context *context }
0096
0097 %%
0098
0099 empty : /* nothing */ ;
0100
0101 regexp : expression { setParseResult( $<regexp>1, context ) ; }
0102 | empty { setParseResult( new ConcRegExp( false ), context ); }
0103 ;
0104
0105 expression : expression TOK_Bar term {
0106 if ( dynamic_cast<AltnRegExp*>( $<regexp>1 ) ) {
0107 $<regexp>$ = $<regexp>1;
0108 }
0109 else {
0110 $<regexp>$ = new AltnRegExp( false );
0111 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>1 );
0112 }
0113 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>3 );
0114 }
0115 | term { $<regexp>$ = $<regexp>1; }
0116 | expression TOK_Bar {
0117 if ( dynamic_cast<AltnRegExp*>( $<regexp>1 ) ) {
0118 $<regexp>$ = $<regexp>1;
0119 }
0120 else {
0121 $<regexp>$ = new AltnRegExp( false );
0122 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>1 );
0123 }
0124 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) );
0125 }
0126 | TOK_Bar term {
0127 $<regexp>$ = new AltnRegExp( false );
0128 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) );
0129 dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>2 );
0130 }
0131 | TOK_Bar { $<regexp>$ = new AltnRegExp( false ); }
0132 ;
0133
0134 term : term factor {
0135 RegExp* last = dynamic_cast<ConcRegExp*>( $<regexp>1 )->lastRegExp();
0136 TextRegExp *reg1, *reg2;
0137
0138 if ( last && ( reg1 = dynamic_cast<TextRegExp*>( last ) ) &&
0139 ( reg2 = dynamic_cast<TextRegExp*>( $<regexp>2 ) ) ) {
0140 reg1->append( reg2->text() );
0141 delete reg2;
0142 }
0143 else {
0144 dynamic_cast<ConcRegExp*>($<regexp>$)->addRegExp( $<regexp>2 );
0145 }
0146 $<regexp>$ = $<regexp>1;
0147 }
0148 | factor {
0149 ConcRegExp* reg = new ConcRegExp( false );
0150 reg->addRegExp( $<regexp>1 );
0151 $<regexp>$ = reg;
0152 }
0153 ;
0154
0155 factor : atom TOK_Quantifier {
0156 $<regexp>$ = new RepeatRegExp( false, $<range>2.min, $<range>2.max, $<regexp>1 );
0157 }
0158 | atom { $<regexp>$ = $<regexp>1; }
0159 ;
0160
0161 atom : TOK_LeftParen expression TOK_RightParent {
0162 $<regexp>$ = $<regexp>2;
0163 }
0164 | TOK_MagicLeftParent expression TOK_RightParent { $<regexp>$ = $<regexp>2; }
0165 | TOK_PosLookAhead expression TOK_RightParent {
0166 $<regexp>$ = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE, $<regexp>2 );
0167 }
0168 | TOK_NegLookAhead expression TOK_RightParent {
0169 $<regexp>$ = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE, $<regexp>2 );
0170 }
0171 | TOK_CharClass { $<regexp>$ = $<regexp>1; }
0172 | char { $<regexp>$ = $<regexp>1; }
0173 | TOK_Dollar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::ENDLINE ); }
0174 | TOK_Carat { $<regexp>$ = new PositionRegExp( false, PositionRegExp::BEGLINE ); }
0175 | TOK_Dot { $<regexp>$ = new DotRegExp( false ); }
0176 | TOK_BackRef {
0177 QString match = QString::fromLocal8Bit("\\%1").arg( $<backRef>1 );
0178 $<regexp>$ = new TextRegExp( false, match );
0179 context->backrefs << match;
0180 }
0181 | TOK_PosWordChar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); }
0182 | TOK_PosNonWordChar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); }
0183 ;
0184
0185 char : TOK_Char {
0186 if ( $<ch>1 == '{' || $<ch>1 == '}' || $<ch>1 == '[' || $<ch>1 == ']' || $<ch>1 == '\\' ) {
0187 yyerror( scanner, context, "illigal character - needs escaping" );
0188 }
0189 $<regexp>$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($<ch>1));
0190 }
0191 | TOK_EscapeChar { $<regexp>$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($<ch>1)); }
0192 ;
0193
0194 %%
0195
0196 RegExp* parseQtRegExp( const QString &qstr, bool* ok ) {
0197 struct parse_context context;
0198 yyscan_t scanner;
0199 context.result = 0;
0200 context.nerrs = 0;
0201 scannerInit( &scanner, &context, qstr );
0202 (void) yyparse( scanner, &context );
0203 scannerDestroy( scanner );
0204 for (const QString &match : std::as_const(context.backrefs)) {
0205 KMessageBox::information(nullptr,i18n("<p>Back reference regular expressions are not supported.</p>"
0206 "<p><tt>\\1</tt>, <tt>\\2</tt>, ... are <i>back references</i>, meaning they "
0207 "refer to previous matches. "
0208 "Unfortunately this is not supported in the current version of this editor.</p>"
0209 "<p>In the graphical area the text <b>%1</b> has been inserted. This is however "
0210 "just a workaround to ensure that the application handles the regexp at all. "
0211 "Therefore, as soon as you edit the regular expression in the graphical area, "
0212 "the back reference will be replaced by matching the text <b>%2</b> literally.</p>",
0213 match, match ),
0214 i18n("Back reference regular expressions not supported"),
0215 QString::fromLocal8Bit("backReferenceNotSupported") );
0216 }
0217 *ok = ( context.nerrs == 0 );
0218 return context.result;
0219 }
0220
0221 void setParseResult( RegExp* regexp, struct parse_context* context ) {
0222 context->result = regexp;
0223 }
0224
0225 int yyerror( yyscan_t, struct parse_context* context, const char * ) {
0226 context->nerrs++;
0227 return 0;
0228 }