From 6f79979ab8847a264459213a61cc501d22fe2964 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 24 Feb 2017 12:31:55 +0100 Subject: [PATCH] RegExp: fix python regex conditional reference parsing --- .../intellij/lang/regexp/RegExpParser.java | 13 ++- .../lang/regexp/RegExpParsingTest.java | 1 + RegExpSupport/testData/psi/Groups39.txt | 91 +++++++++---------- RegExpSupport/testData/psi/Groups40.txt | 53 ++++++----- RegExpSupport/testData/psi/Groups43.txt | 85 +++++++++++++++++ 5 files changed, 169 insertions(+), 74 deletions(-) create mode 100644 RegExpSupport/testData/psi/Groups43.txt diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java index 4650f62df3ee..3412ead6d63d 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java @@ -391,7 +391,18 @@ public class RegExpParser implements PsiParser { builder.error("Group name or number expected"); } checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group reference"); - parseGroupEnd(builder); + if (!parseBranch(builder)) { + patternExpected(builder); + } + else { + if (builder.getTokenType() == RegExpTT.UNION) { + builder.advanceLexer(); + if (!parseBranch(builder)) { + patternExpected(builder); + } + } + checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group"); + } marker.done(RegExpElementTypes.PY_COND_REF); } else if (type == RegExpTT.PROPERTY) { diff --git a/RegExpSupport/test/org/intellij/lang/regexp/RegExpParsingTest.java b/RegExpSupport/test/org/intellij/lang/regexp/RegExpParsingTest.java index a81dd79e2622..4b809d887999 100644 --- a/RegExpSupport/test/org/intellij/lang/regexp/RegExpParsingTest.java +++ b/RegExpSupport/test/org/intellij/lang/regexp/RegExpParsingTest.java @@ -193,6 +193,7 @@ public class RegExpParsingTest extends ParsingTestCase { public void testGroups40() throws IOException { doCodeTest("(?(name)yes-pattern|{"); } public void testGroups41() throws IOException { doCodeTest("(?>atomic)"); } public void testGroups42() throws IOException { doCodeTest("(?:non-capturing)"); } + public void testGroups43() throws IOException { doCodeTest("(?(name)yes-pattern|no_pattern|maybe-pattern)"); } public void testEscapes1() throws IOException { doCodeTest("\\q"); } public void testEscapes2() throws IOException { doCodeTest("\\#"); } diff --git a/RegExpSupport/testData/psi/Groups39.txt b/RegExpSupport/testData/psi/Groups39.txt index 876b3d744dd5..f473d213aa49 100644 --- a/RegExpSupport/testData/psi/Groups39.txt +++ b/RegExpSupport/testData/psi/Groups39.txt @@ -5,50 +5,49 @@ REGEXP_FILE PsiElement(PYTHON_COND_REF)('(?(') PsiElement(NAME)('name') PsiElement(GROUP_END)(')') - RegExpPatternImpl: - RegExpBranchImpl: - RegExpCharImpl: - PsiElement(CHARACTER)('y') - RegExpCharImpl: - PsiElement(CHARACTER)('e') - RegExpCharImpl: - PsiElement(CHARACTER)('s') - RegExpCharImpl: <-> - PsiElement(CHARACTER)('-') - RegExpCharImpl:

- PsiElement(CHARACTER)('p') - RegExpCharImpl: - PsiElement(CHARACTER)('a') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('e') - RegExpCharImpl: - PsiElement(CHARACTER)('r') - RegExpCharImpl: - PsiElement(CHARACTER)('n') - PsiElement(UNION)('|') - RegExpBranchImpl: - RegExpCharImpl: - PsiElement(CHARACTER)('n') - RegExpCharImpl: - PsiElement(CHARACTER)('o') - RegExpCharImpl: <-> - PsiElement(CHARACTER)('-') - RegExpCharImpl:

- PsiElement(CHARACTER)('p') - RegExpCharImpl: - PsiElement(CHARACTER)('a') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('e') - RegExpCharImpl: - PsiElement(CHARACTER)('r') - RegExpCharImpl: - PsiElement(CHARACTER)('n') + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('y') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('s') + RegExpCharImpl: <-> + PsiElement(CHARACTER)('-') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') + PsiElement(UNION)('|') + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('n') + RegExpCharImpl: + PsiElement(CHARACTER)('o') + RegExpCharImpl: <-> + PsiElement(CHARACTER)('-') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') PsiElement(GROUP_END)(')') \ No newline at end of file diff --git a/RegExpSupport/testData/psi/Groups40.txt b/RegExpSupport/testData/psi/Groups40.txt index 2b06a7323922..12e58af412e9 100644 --- a/RegExpSupport/testData/psi/Groups40.txt +++ b/RegExpSupport/testData/psi/Groups40.txt @@ -6,33 +6,32 @@ REGEXP_FILE PsiElement(PYTHON_COND_REF)('(?(') PsiElement(NAME)('name') PsiElement(GROUP_END)(')') - RegExpPatternImpl: - RegExpBranchImpl: - RegExpCharImpl: - PsiElement(CHARACTER)('y') - RegExpCharImpl: - PsiElement(CHARACTER)('e') - RegExpCharImpl: - PsiElement(CHARACTER)('s') - RegExpCharImpl: <-> - PsiElement(CHARACTER)('-') - RegExpCharImpl:

- PsiElement(CHARACTER)('p') - RegExpCharImpl: - PsiElement(CHARACTER)('a') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('t') - RegExpCharImpl: - PsiElement(CHARACTER)('e') - RegExpCharImpl: - PsiElement(CHARACTER)('r') - RegExpCharImpl: - PsiElement(CHARACTER)('n') - PsiElement(UNION)('|') - PsiErrorElement:Dangling metacharacter - + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('y') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('s') + RegExpCharImpl: <-> + PsiElement(CHARACTER)('-') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') + PsiElement(UNION)('|') + PsiErrorElement:Dangling metacharacter + RegExpQuantifierImpl: <{> PsiElement(LBRACE)('{') PsiErrorElement:Number expected diff --git a/RegExpSupport/testData/psi/Groups43.txt b/RegExpSupport/testData/psi/Groups43.txt new file mode 100644 index 000000000000..5c375073825e --- /dev/null +++ b/RegExpSupport/testData/psi/Groups43.txt @@ -0,0 +1,85 @@ +REGEXP_FILE + RegExpPatternImpl: <(?(name)yes-pattern|no_pattern|maybe-pattern> + RegExpBranchImpl: <(?(name)yes-pattern|no_pattern> + RegExpPyCondRefImpl: <(?(name)yes-pattern|no_pattern> + PsiElement(PYTHON_COND_REF)('(?(') + PsiElement(NAME)('name') + PsiElement(GROUP_END)(')') + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('y') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('s') + RegExpCharImpl: <-> + PsiElement(CHARACTER)('-') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') + PsiElement(UNION)('|') + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('n') + RegExpCharImpl: + PsiElement(CHARACTER)('o') + RegExpCharImpl: <_> + PsiElement(CHARACTER)('_') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') + PsiErrorElement:Unclosed group + + PsiElement(UNION)('|') + RegExpBranchImpl: + RegExpCharImpl: + PsiElement(CHARACTER)('m') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('y') + RegExpCharImpl: + PsiElement(CHARACTER)('b') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: <-> + PsiElement(CHARACTER)('-') + RegExpCharImpl:

+ PsiElement(CHARACTER)('p') + RegExpCharImpl: + PsiElement(CHARACTER)('a') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('t') + RegExpCharImpl: + PsiElement(CHARACTER)('e') + RegExpCharImpl: + PsiElement(CHARACTER)('r') + RegExpCharImpl: + PsiElement(CHARACTER)('n') + PsiErrorElement:Unmatched closing ')' + + PsiElement(GROUP_END)(')') \ No newline at end of file