IntelliLang and stuff
authorgreg <Gregory.Shrago@jetbrains.com>
Fri, 18 Apr 2008 11:36:57 +0000 (15:36 +0400)
committergreg <Gregory.Shrago@jetbrains.com>
Fri, 18 Apr 2008 11:36:57 +0000 (15:36 +0400)
152 files changed:
RegExpSupport/RegExpSupport.iml [new file with mode: 0644]
RegExpSupport/build.xml [new file with mode: 0644]
RegExpSupport/regexp-lang-java.iml [new file with mode: 0644]
RegExpSupport/regexp-lang.iml [new file with mode: 0644]
RegExpSupport/regexp-lang.ipr [new file with mode: 0644]
RegExpSupport/regexp-lang.xml [new file with mode: 0644]
RegExpSupport/src/META-INF/plugin.xml [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpElementType.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpElementTypes.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpFileType.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguage.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpSupportLoader.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/RegExpTT.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpAtom.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBackref.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBoundary.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBranch.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpChar.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpCharRange.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClass.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClassElement.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClosure.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElement.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElementVisitor.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpGroup.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpIntersection.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpOptions.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpPattern.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpProperty.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpQuantifier.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpRecursiveElementVisitor.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSetOptions.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSimpleClass.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBackrefImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBoundaryImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBranchImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharRangeImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClassImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClosureImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpGroupImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpIntersectionImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpOptionsImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPatternImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPropertyImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpQuantifierImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSetOptionsImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSimpleClassImpl.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/regexp-filetype-icon.png [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/surroundWith/GroupSurrounder.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/surroundWith/SimpleSurroundDescriptor.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/validation/RemoveRedundantEscapeAction.java [new file with mode: 0644]
RegExpSupport/src/org/intellij/lang/regexp/validation/SimplifyQuantifierAction.java [new file with mode: 0644]
RegExpSupport/test/test/BaseParseTestcase.java [new file with mode: 0644]
RegExpSupport/test/test/Main.java [new file with mode: 0644]
RegExpSupport/test/test/MainParseTest.java [new file with mode: 0644]
RegExpSupport/test/test/ParseTest.java [new file with mode: 0644]
RegExpSupport/testData/RETest.xml [new file with mode: 0644]
RegExpSupport/testData/psi/test1.regexp [new file with mode: 0644]
RegExpSupport/testData/psi/test2.regexp [new file with mode: 0644]
RegExpSupport/testData/psi/test3.regexp [new file with mode: 0644]
RegExpSupport/testData/psi/test4.regexp [new file with mode: 0644]
plugins/IntelliLang/IntelliLang-standalone.ipr [new file with mode: 0644]
plugins/IntelliLang/IntelliLang.iml [new file with mode: 0644]
plugins/IntelliLang/IntelliLang.xml [new file with mode: 0644]
plugins/IntelliLang/IntelliLangJava.iml [new file with mode: 0644]
plugins/IntelliLang/LICENSE [new file with mode: 0644]
plugins/IntelliLang/build.xml [new file with mode: 0644]
plugins/IntelliLang/help/help.jar [new file with mode: 0644]
plugins/IntelliLang/src/LanguageInjectionConfiguration.xml [new file with mode: 0644]
plugins/IntelliLang/src/META-INF/plugin.xml [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/InjectionNotApplicable.html [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/LanguageMismatch.html [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/PatternNotApplicable.html [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/PatternOverriddenByNonAnnotatedMethod.html [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/PatternValidation.html [new file with mode: 0644]
plugins/IntelliLang/src/inspectionDescriptions/UnknownLanguage.html [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Settings.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/SettingsUI.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/icon.png [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/icon_small.png [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjector.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageReference.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageReferenceProvider.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/RegExpEnumReference.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/Injection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/XPathSupportProxy.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/InjectionPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/ValueRegExpAnnotator.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/InjectionConfigurable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/MethodParameterInjectionConfigurable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlAttributeInjectionConfigurable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlTagInjectionConfigurable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditEditor.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/validation/InjectionNotApplicable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/validation/InspectionProvider.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/validation/LanguageMismatch.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/validation/UnknownLanguageID.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/InspectionProvider.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/PatternAnnotationNotApplicable.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/PatternOverriddenByNonAnnotatedMethod.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/PatternValidator.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/AnnotationBasedInstrumentingCompiler.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/InstrumentationException.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/InstrumentationItem.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/Instrumenter.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/impl/InstrumentationAdapter.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/impl/PatternValidationCompiler.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/pattern/compiler/impl/PatternValidationInstrumenter.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/AnnotateFix.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/AnnotationUtilEx.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/ContextComputationProcessor.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/InitializerRequirement.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/LanguageTextField.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/PsiUtilEx.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/RegExpUtil.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/RemoveAnnotationFix.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/ShiftTabAction.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/StringLiteralReference.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/StringMatcher.java [new file with mode: 0644]
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/util/SubstitutedExpressionEvaluationHelper.java [new file with mode: 0644]

diff --git a/RegExpSupport/RegExpSupport.iml b/RegExpSupport/RegExpSupport.iml
new file mode 100644 (file)
index 0000000..bc6498a
--- /dev/null
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+  <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" />
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <output url="file://$MODULE_DIR$/build/classes/production" />
+    <output-test url="file://$MODULE_DIR$/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="lang-api" />
+    <orderEntry type="module" module-name="openapi" />
+    <orderEntry type="library" name="JUnit4" level="project" />
+    <orderEntryProperties />
+  </component>
+  <component name="RetroweaverPlugin">
+    <setting name="active" value="false" />
+    <setting name="verbose" value="false" />
+    <setting name="verifyrefs" value="false" />
+    <setting name="targetJDK" value="" />
+  </component>
+  <component name="copyright">
+    <Base>
+      <setting name="state" value="1" />
+    </Base>
+    <LanguageOptions name="$TEMPLATE$">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="CSS">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="HTML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JAVA">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="/*&#10; * Copyright (c) &amp;#36;today.year Your Corporation. All Rights Reserved.&#10; */" />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JSP">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JavaScript">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="Properties">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="XML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+  </component>
+</module>
+
diff --git a/RegExpSupport/build.xml b/RegExpSupport/build.xml
new file mode 100644 (file)
index 0000000..2c42562
--- /dev/null
@@ -0,0 +1,120 @@
+<project default="zips" name="Regular Expression Support">
+
+  <property file="regexp-lang.properties" />
+
+  <fail unless="jdk.home.idea_8.0">
+    Please set the property 'jdk.home.idea_8.0' to point to your IntelliJ IDEA 8.0 installation directory.
+  </fail>
+
+  <!-- override for embedded build -->
+  <property name="src.zip" value="build/src_RegExpSupport.zip" />
+  <property name="src.zip.update" value="false" />
+
+  <import file="regexp-lang.xml" />
+
+  <path id="jdk.bootclasspath.idea_6.0">
+    <path>
+      <fileset dir="${jdk.home.idea_8.0}">
+        <include name="jre/lib/charsets.jar" />
+        <include name="jre/lib/deploy.jar" />
+        <include name="jre/lib/javaws.jar" />
+        <include name="jre/lib/jce.jar" />
+        <include name="jre/lib/jsse.jar" />
+        <include name="jre/lib/plugin.jar" />
+        <include name="jre/lib/rt.jar" />
+        <include name="jre/lib/resources.jar" />
+        <include name="jre/lib/tools.jar" />
+        <include name="jre/lib/ext/dnsns.jar" />
+        <include name="jre/lib/ext/localedata.jar" />
+        <include name="jre/lib/ext/sunjce_provider.jar" />
+        <include name="jre/lib/ext/sunpkcs11.jar" />
+      </fileset>
+    </path>
+    <pathelement location="${jdk.home.idea_8.0}/lib/boot.jar" />
+  </path>
+
+  <target name="build" depends="jflex, all" />
+
+  <target name="jar" depends="build">
+    <mkdir dir="build" />
+    <jar file="build/RegExpSupport.jar" compress="false">
+      <fileset dir="${regexp-lang.output.dir}">
+        <include name="**/*.*" />
+        <exclude name="${excluded-stuff}" />
+      </fileset>
+      <fileset dir=".">
+        <include name="META-INF/plugin.xml" unless="regexp-lang.embedded"/>
+      </fileset>
+    </jar>
+  </target>
+
+  <target name="jflex">
+    <taskdef name="jflex" classname="JFlex.anttask.JFlexTask">
+      <classpath location="${jdk.home.idea_8.0}/tools/jflex/lib/JFlex.jar" />
+    </taskdef>
+
+    <jflex skeleton="${jdk.home.idea_8.0}/tools/jflex/idea-flex.skeleton"
+           file="src/org/intellij/lang/regexp/regexp-lexer.flex"
+           destdir="src"
+           nobak="true"
+           charat="true" />
+  </target>
+
+  <target name="test" depends="build" description="run tests">
+    <junit fork="true" dir="${basedir}" failureproperty="junit.failed" errorproperty="junit.failed">
+      <sysproperty key="idea.load.plugins" value="false" />
+
+      <bootclasspath refid="jdk.bootclasspath.idea_6.0" />
+      <classpath refid="jdk.classpath.idea_8.0" />
+
+      <classpath>
+        <pathelement location="${regexp-lang.output.dir}" />
+        <pathelement location="${regexp-lang.testoutput.dir}" />
+      </classpath>
+
+      <test name="test.MainParseTest">
+        <formatter type="plain" />
+      </test>
+    </junit>
+
+    <fail if="junit.failed" />
+  </target>
+
+  <target name="src.zip">
+    <zip file="${src.zip}" update="${src.zip.update}">
+      <zipfileset dir="src" prefix="RegExpSupport/src">
+        <include name="org/**/*.java" />
+        <include name="org/**/*.png" />
+        <include name="**/*.flex" />
+      </zipfileset>
+      <zipfileset dir="test" prefix="RegExpSupport/test">
+        <include name="**/*.java" />
+      </zipfileset>
+      <zipfileset dir="testData" prefix="RegExpSupport/testData">
+        <include name="**/*.regexp" />
+        <exclude name="psi/gen/**/*" />
+        <include name="**/*.xml" />
+      </zipfileset>
+      <zipfileset dir="." prefix="RegExpSupport">
+        <include name="build.xml" />
+        <include name="log4j.dtd" />
+        <include name="regexp-lang.xml" />
+        <include name="regexp-lang.ipr" />
+        <include name="regexp-lang.iml" />
+        <include name="regexp-lang-java.iml" />
+        <include name="META-INF/plugin.xml" />
+      </zipfileset>
+    </zip>
+  </target>
+
+  <target name="bin.zip" depends="jar">
+    <zip file="build/RegExpSupport.zip">
+      <zipfileset dir="build" prefix="RegExpSupport/lib">
+        <include name="*.jar" />
+      </zipfileset>
+    </zip>
+  </target>
+
+  <target name="zips" depends="bin.zip, src.zip" />
+
+</project>
diff --git a/RegExpSupport/regexp-lang-java.iml b/RegExpSupport/regexp-lang-java.iml
new file mode 100644 (file)
index 0000000..e42fa60
--- /dev/null
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <output url="file://$MODULE_DIR$/build/classes/production" />
+    <output-test url="file://$MODULE_DIR$/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+  <component name="copyright">
+    <Base>
+      <setting name="state" value="1" />
+    </Base>
+    <LanguageOptions name="$TEMPLATE$">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright 2006 Sascha Weinreuter&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;    http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
+      <option name="keyword" value="Copyright|Created by IntelliJ IDEA" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="CSS">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="HTML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JAVA">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="/*&#10; * Copyright (c) &amp;#36;today.year Your Corporation. All Rights Reserved.&#10; */" />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JSP">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JavaScript">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="Properties">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="XML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="1" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+  </component>
+</module>
+
diff --git a/RegExpSupport/regexp-lang.iml b/RegExpSupport/regexp-lang.iml
new file mode 100644 (file)
index 0000000..2f2d19b
--- /dev/null
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+  <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" />
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <output url="file://$MODULE_DIR$/build/classes/production" />
+    <output-test url="file://$MODULE_DIR$/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="lang-api" />
+    <orderEntry type="module" module-name="openapi" />
+    <orderEntry type="library" name="JUnit4" level="project" />
+    <orderEntryProperties />
+  </component>
+  <component name="RetroweaverPlugin">
+    <setting name="active" value="false" />
+    <setting name="verbose" value="false" />
+    <setting name="verifyrefs" value="false" />
+    <setting name="targetJDK" value="" />
+  </component>
+  <component name="copyright">
+    <Base>
+      <setting name="state" value="1" />
+    </Base>
+    <LanguageOptions name="$TEMPLATE$">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="CSS">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="HTML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JAVA">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="/*&#10; * Copyright (c) &amp;#36;today.year Your Corporation. All Rights Reserved.&#10; */" />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JSP">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JavaScript">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="Properties">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="XML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+  </component>
+</module>
+
diff --git a/RegExpSupport/regexp-lang.ipr b/RegExpSupport/regexp-lang.ipr
new file mode 100644 (file)
index 0000000..26aad13
--- /dev/null
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4" relativePaths="false">
+  <component name="AntConfiguration">
+    <defaultAnt bundledAnt="true" />
+  </component>
+  <component name="BuildJarProjectSettings">
+    <option name="BUILD_JARS_ON_MAKE" value="false" />
+  </component>
+  <component name="CodeStyleProjectProfileManger">
+    <option name="PROJECT_PROFILE" />
+    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+    <scopes />
+    <profiles />
+  </component>
+  <component name="CodeStyleSettingsManager">
+    <option name="PER_PROJECT_SETTINGS" />
+    <option name="USE_PER_PROJECT_SETTINGS" value="false" />
+  </component>
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <option name="DEPLOY_AFTER_MAKE" value="0" />
+    <resourceExtensions>
+      <entry name=".+\.(properties|xml|html|dtd|tld)" />
+      <entry name=".+\.(gif|png|jpeg|jpg)" />
+    </resourceExtensions>
+    <wildcardResourcePatterns>
+      <entry name="?*.properties" />
+      <entry name="?*.xml" />
+      <entry name="?*.gif" />
+      <entry name="?*.png" />
+      <entry name="?*.jpeg" />
+      <entry name="?*.jpg" />
+      <entry name="?*.html" />
+      <entry name="?*.dtd" />
+      <entry name="?*.tld" />
+    </wildcardResourcePatterns>
+  </component>
+  <component name="DataSourceManagerImpl" />
+  <component name="DependenciesAnalyzeManager">
+    <option name="myForwardDirection" value="false" />
+  </component>
+  <component name="DependencyValidationManager" />
+  <component name="EclipseCompilerSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="true" />
+    <option name="DEPRECATION" value="false" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="EclipseEmbeddedCompilerSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="true" />
+    <option name="DEPRECATION" value="false" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="EntryPointsManager">
+    <entry_points />
+  </component>
+  <component name="ExportToHTMLSettings">
+    <option name="PRINT_LINE_NUMBERS" value="false" />
+    <option name="OPEN_IN_BROWSER" value="false" />
+    <option name="OUTPUT_DIRECTORY" />
+  </component>
+  <component name="GUI Designer component loader factory" />
+  <component name="IdProvider" IDEtalkID="5C9C3E71CFACA17DE96A59189C36AF1D" />
+  <component name="InspectionProjectProfileManager">
+    <option name="PROJECT_PROFILE" value="Project Default" />
+    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+    <scopes />
+    <profiles>
+      <profile version="1.0">
+        <option name="myName" value="Project Default" />
+        <option name="myLocal" value="false" />
+        <used_levels>
+          <error>
+            <option name="myName" value="ERROR" />
+            <option name="myVal" value="200" />
+          </error>
+          <warning>
+            <option name="myName" value="WARNING" />
+            <option name="myVal" value="100" />
+          </warning>
+          <information>
+            <option name="myName" value="INFO" />
+            <option name="myVal" value="100" />
+          </information>
+          <server>
+            <option name="myName" value="SERVER PROBLEM" />
+            <option name="myVal" value="100" />
+          </server>
+        </used_levels>
+        <inspection_tool class="ClassReferencesSubclass" level="WARNING" enabled="true" />
+        <inspection_tool class="MalformedXPath" level="WARNING" enabled="false" />
+        <inspection_tool class="UtilityClassWithoutPrivateConstructor" level="WARNING" enabled="true">
+          <option name="ignoreClassesWithOnlyMain" value="false" />
+        </inspection_tool>
+        <inspection_tool class="CloneDeclaresCloneNotSupported" level="WARNING" enabled="false" />
+        <inspection_tool class="CloneInNonCloneableClass" level="WARNING" enabled="true" />
+        <inspection_tool class="MultipleTypedDeclaration" level="WARNING" enabled="true" />
+        <inspection_tool class="PointlessIndexOfComparison" level="WARNING" enabled="true" />
+        <inspection_tool class="TooBroadScope" level="WARNING" enabled="true">
+          <option name="m_allowConstructorAsInitializer" value="false" />
+          <option name="m_onlyLookAtBlocks" value="false" />
+        </inspection_tool>
+        <inspection_tool class="MethodOnlyUsedFromNestedClass" level="WARNING" enabled="true" />
+        <inspection_tool class="CastToIncompatibleInterface" level="WARNING" enabled="true" />
+        <inspection_tool class="EqualsBetweenInconvertibleTypes" level="WARNING" enabled="true" />
+      </profile>
+    </profiles>
+  </component>
+  <component name="JavacSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="false" />
+    <option name="DEPRECATION" value="true" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="JavadocGenerationManager">
+    <option name="OUTPUT_DIRECTORY" />
+    <option name="OPTION_SCOPE" value="protected" />
+    <option name="OPTION_HIERARCHY" value="true" />
+    <option name="OPTION_NAVIGATOR" value="true" />
+    <option name="OPTION_INDEX" value="true" />
+    <option name="OPTION_SEPARATE_INDEX" value="true" />
+    <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+    <option name="OPTION_DEPRECATED_LIST" value="true" />
+    <option name="OTHER_OPTIONS" value="" />
+    <option name="HEAP_SIZE" />
+    <option name="LOCALE" />
+    <option name="OPEN_IN_BROWSER" value="true" />
+  </component>
+  <component name="JikesSettings">
+    <option name="JIKES_PATH" value="" />
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="DEPRECATION" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="false" />
+    <option name="IS_EMACS_ERRORS_MODE" value="true" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+  </component>
+  <component name="LogConsolePreferences">
+    <option name="FILTER_ERRORS" value="false" />
+    <option name="FILTER_WARNINGS" value="false" />
+    <option name="FILTER_INFO" value="true" />
+    <option name="CUSTOM_FILTER" />
+  </component>
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/regexp-lang.iml" filepath="$PROJECT_DIR$/regexp-lang.iml" />
+    </modules>
+  </component>
+  <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA Demetra" project-jdk-type="IDEA JDK">
+    <output url="file://$PROJECT_DIR$/classes" />
+  </component>
+  <component name="ProjectRunConfigurationManager">
+    <configuration default="false" name="regexp-lang" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
+      <module name="regexp-lang" />
+      <option name="VM_PARAMETERS" value="-ea -Drpc.port=38387" />
+      <option name="PROGRAM_PARAMETERS" value="" />
+      <log_file path="$APPLICATION_HOME_DIR$/sandbox/system/log/idea.log" checked="false" skipped="true" show_all="false" alias="IDEA LOG" />
+      <RunnerSettings RunnerId="Debug">
+        <option name="DEBUG_PORT" value="2437" />
+        <option name="TRANSPORT" value="0" />
+        <option name="LOCAL" value="true" />
+      </RunnerSettings>
+      <ConfigurationWrapper RunnerId="Debug" />
+      <method>
+        <option name="Make" value="true" />
+      </method>
+    </configuration>
+  </component>
+  <component name="RmicSettings">
+    <option name="IS_EANABLED" value="false" />
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="false" />
+    <option name="GENERATE_IIOP_STUBS" value="false" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+  </component>
+  <component name="StarteamVcsAdapter" />
+  <component name="VssVcs" />
+  <component name="copyright">
+    <Base>
+      <setting name="state" value="2" />
+    </Base>
+    <LanguageOptions name="$TEMPLATE$">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="CSS">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="HTML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JAVA">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="/*&#10; * Copyright (c) &amp;#36;today.year Your Corporation. All Rights Reserved.&#10; */" />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="4" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JSP">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="JavaScript">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="Properties">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+    <LanguageOptions name="XML">
+      <option name="templateOptions">
+        <value>
+          <option name="block" value="true" />
+          <option name="separateBefore" value="false" />
+          <option name="separateAfter" value="false" />
+          <option name="prefixLines" value="true" />
+          <option name="lenBefore" value="80" />
+          <option name="lenAfter" value="80" />
+          <option name="box" value="false" />
+          <option name="filler" value=" " />
+        </value>
+      </option>
+      <option name="notice" value="Copyright (c) &amp;#36;today.year, Your Corporation. All Rights Reserved." />
+      <option name="keyword" value="Copyright" />
+      <option name="fileTypeOverride" value="2" />
+      <option name="relativeBefore" value="true" />
+      <option name="addBlankAfter" value="true" />
+      <option name="fileLocation" value="1" />
+      <option name="useAlternate" value="false" />
+    </LanguageOptions>
+  </component>
+  <component name="libraryTable" />
+  <component name="uidesigner-configuration">
+    <option name="INSTRUMENT_CLASSES" value="true" />
+    <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
+    <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" />
+  </component>
+  <UsedPathMacros />
+</project>
+
diff --git a/RegExpSupport/regexp-lang.xml b/RegExpSupport/regexp-lang.xml
new file mode 100644 (file)
index 0000000..c6ba851
--- /dev/null
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="RegExpSupport" default="all">
+
+  <property file="regexp-lang.properties" />
+  
+  <!-- Uncomment the following property if no tests compilation is needed -->
+  <!-- 
+  <property name="skip.tests" value="true"/>
+   -->
+
+  <!-- The task requires the following libraries from IntelliJ IDEA distribution: -->
+  <!--   javac2.jar; jdom.jar; asm.jar; asm-commons.jar -->
+  <taskdef name="javac2" classname="com.intellij.ant.Javac2">
+    <classpath refid="classpath.uidesigner" />
+  </taskdef>
+
+  <path id="classpath.uidesigner">
+    <path refid="jdk.classpath.idea_8.0" />
+    <path>
+      <fileset dir="${jdk.home.idea_8.0}">
+        <include name="redist/javac2.jar" />
+      </fileset>
+    </path>
+  </path>
+
+  <!-- Compiler options -->
+
+  <property name="compiler.debug" value="on" />
+  <property name="compiler.generate.no.warnings" value="off" />
+  <property name="compiler.args" value="" />
+  <property name="compiler.max.memory" value="128m" />
+  <patternset id="ignored.files">
+    <exclude name="**/CVS/**" />
+    <exclude name="**/SCCS/**" />
+    <exclude name="**/RCS/**" />
+    <exclude name="**/rcs/**" />
+    <exclude name="**/.dependency-info/**" />
+    <exclude name="**/.svn/**" />
+  </patternset>
+  <patternset id="compiler.excluded">
+  </patternset>
+  <patternset id="compiler.resources">
+    <include name="**/?*.properties" />
+    <include name="**/?*.xml" />
+    <include name="**/?*.html" />
+    <include name="**/?*.gif" />
+    <include name="**/?*.png" />
+    <include name="**/?*.jpeg" />
+    <include name="**/?*.xsd" />
+    <include name="**/?*.xsl" />
+    <include name="**/?*.xhtml" />
+    <include name="**/?*.template" />
+  </patternset>
+
+  <!-- JDK definitions -->
+
+  <path id="jdk.classpath.idea_8.0">
+    <fileset dir="${jdk.home.idea_8.0}">
+      <include name="lib/*.jar" />
+
+      <include name="lib/tools.jar"/>
+    </fileset>
+  </path>
+
+  <property name="project.jdk.home" value="${jdk.home.idea_8.0}" />
+  <property name="project.jdk.classpath" value="jdk.classpath.idea_8.0" />
+
+
+  <!-- Global Libraries -->
+
+  <!-- Application Server Libraries -->
+
+  <!-- Modules -->
+
+
+  <!-- Module regexp-lang -->
+
+  <dirname property="module.regexp-lang.basedir" file="${ant.file}" />
+
+
+  <property name="module.jdk.home.regexp-lang" value="${project.jdk.home}" />
+  <property name="module.jdk.classpath.regexp-lang" value="${project.jdk.classpath}" />
+
+  <property name="compiler.args.regexp-lang" value="${compiler.args}" />
+
+  <property name="regexp-lang.output.dir" value="${module.regexp-lang.basedir}/build/classes/production" />
+  <property name="regexp-lang.testoutput.dir" value="${module.regexp-lang.basedir}/build/classes/test" />
+
+  <path id="regexp-lang.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+
+  <path id="regexp-lang.module.classpath">
+    <path refid="${module.jdk.classpath.regexp-lang}" />
+  </path>
+
+
+  <patternset id="excluded.from.module.regexp-lang">
+    <patternset refid="ignored.files" />
+  </patternset>
+
+  <patternset id="excluded.from.compilation.regexp-lang">
+    <patternset refid="compiler.excluded" />
+    <patternset refid="excluded.from.module.regexp-lang" />
+  </patternset>
+
+  <path id="regexp-lang.module.sourcepath">
+    <dirset dir="${module.regexp-lang.basedir}">
+      <include name="src" />
+    </dirset>
+  </path>
+
+  <path id="regexp-lang.module.test.sourcepath">
+    <dirset dir="${module.regexp-lang.basedir}">
+      <include name="test" />
+    </dirset>
+  </path>
+
+
+  <target name="compile.module.regexp-lang"
+          depends="compile.module.regexp-lang.production,compile.module.regexp-lang.tests"
+          description="Compile module regexp-lang" />
+
+  <target name="compile.module.regexp-lang.production" description="Compile module regexp-lang; production classes">
+    <mkdir dir="${regexp-lang.output.dir}" />
+    <javac2 destdir="${regexp-lang.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}"
+            memorymaximumsize="${compiler.max.memory}" target="1.5">
+      <compilerarg line="${compiler.args.regexp-lang}" />
+      <bootclasspath refid="regexp-lang.module.bootclasspath" />
+      <classpath refid="regexp-lang.module.classpath" />
+      <src refid="regexp-lang.module.sourcepath" />
+      <patternset refid="excluded.from.compilation.regexp-lang" />
+    </javac2>
+
+    <copy todir="${regexp-lang.output.dir}">
+      <fileset dir="${module.regexp-lang.basedir}/src">
+        <patternset refid="compiler.resources" />
+        <type type="file" />
+        <patternset refid="excluded.from.compilation.regexp-lang" />
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="compile.module.regexp-lang.tests" depends="compile.module.regexp-lang.production"
+          description="compile module regexp-lang; test classes" unless="skip.tests">
+    <mkdir dir="${regexp-lang.testoutput.dir}" />
+    <javac2 destdir="${regexp-lang.testoutput.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}"
+            memorymaximumsize="${compiler.max.memory}" target="1.5">
+      <compilerarg line="${compiler.args.regexp-lang}" />
+      <classpath refid="regexp-lang.module.classpath" />
+      <classpath location="${regexp-lang.output.dir}" />
+      <src refid="regexp-lang.module.test.sourcepath" />
+      <patternset refid="excluded.from.compilation.regexp-lang" />
+    </javac2>
+
+    <copy todir="${regexp-lang.testoutput.dir}">
+      <fileset dir="${module.regexp-lang.basedir}/test">
+        <patternset refid="compiler.resources" />
+        <type type="file" />
+        <patternset refid="excluded.from.compilation.regexp-lang" />
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="clean.module.regexp-lang" description="cleanup module">
+    <delete dir="${regexp-lang.output.dir}" />
+    <delete dir="${regexp-lang.testoutput.dir}" />
+  </target>
+
+
+  <target name="init" description="Build initialization">
+    <!-- Perform any build initialization in this target -->
+  </target>
+
+  <target name="clean" depends="clean.module.regexp-lang" description="cleanup all" />
+
+  <target name="all" depends="init, clean, compile.module.regexp-lang" description="build all" />
+</project>
\ No newline at end of file
diff --git a/RegExpSupport/src/META-INF/plugin.xml b/RegExpSupport/src/META-INF/plugin.xml
new file mode 100644 (file)
index 0000000..3e7d086
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE idea-plugin PUBLIC "Plugin/DTD" "http://plugins.intellij.net/plugin.dtd">
+<idea-plugin>
+  <name>Regular Expression Support</name>
+  <id>RegExpLanguage</id>
+
+  <description>
+    Regular Expression Language implementation with full java.util.regex.Pattern syntax support,
+    detailed on-the-fly error highlighting, completion, some intention actions and more.
+  </description>
+
+  <version>1.0</version>
+  <vendor>Sascha Weinreuter</vendor>
+  <idea-version since-build="6656"/>
+  
+  <application-components>
+    <component>
+      <implementation-class>org.intellij.lang.regexp.RegExpSupportLoader</implementation-class>
+    </component>
+  </application-components>
+</idea-plugin>
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpElementType.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpElementType.java
new file mode 100644 (file)
index 0000000..6c5f53a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.lang.Language;
+
+public class RegExpElementType extends IElementType {
+    RegExpElementType(String s) {
+        super(s, Language.findInstance(RegExpLanguage.class));
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpElementTypes.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpElementTypes.java
new file mode 100644 (file)
index 0000000..087c29f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+
+public interface RegExpElementTypes {
+    IFileElementType REGEXP_FILE = new IFileElementType("REGEXP_FILE", RegExpLanguage.INSTANCE);
+    IElementType PATTERN = new RegExpElementType("PATTERN");
+    IElementType BRANCH = new RegExpElementType("BRANCH");
+    IElementType CLOSURE = new RegExpElementType("COUNTED_CLOSURE");
+    IElementType QUANTIFIER = new RegExpElementType("QUANTIFIER");
+    IElementType SIMPLE_CLASS = new RegExpElementType("SIMPLE_CLASS");
+    IElementType CLASS = new RegExpElementType("CLASS");
+    IElementType CHAR_RANGE = new RegExpElementType("CHAR_RANGE");
+    IElementType INTERSECTION = new RegExpElementType("INTERSECTION");
+    IElementType CHAR = new RegExpElementType("CHAR");
+    IElementType GROUP = new RegExpElementType("GROUP");
+    IElementType PROPERTY = new RegExpElementType("PROPERTY");
+    IElementType OPTIONS = new RegExpElementType("OPTIONS");
+    IElementType SET_OPTIONS = new RegExpElementType("SET_OPTIONS");
+    IElementType BACKREF = new RegExpElementType("BACKREF");
+    IElementType BOUNDARY = new RegExpElementType("BOUNDARY");
+
+    TokenSet ATOMS = TokenSet.create(CLOSURE, BOUNDARY,
+            SIMPLE_CLASS, CLASS, CHAR, GROUP, PROPERTY, SET_OPTIONS, BACKREF);
+
+    TokenSet CLASS_ELEMENTS = TokenSet.create(CHAR, CHAR_RANGE,
+            SIMPLE_CLASS, CLASS, INTERSECTION, PROPERTY);
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
new file mode 100644 (file)
index 0000000..9b5afbc
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.extapi.psi.PsiFileBase;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.FileViewProvider;
+import org.jetbrains.annotations.NotNull;
+
+public class RegExpFile extends PsiFileBase {
+
+    public RegExpFile(FileViewProvider viewProvider) {
+        super(viewProvider, RegExpLanguage.INSTANCE);
+    }
+
+    @NotNull
+    public FileType getFileType() {
+        return RegExpFileType.INSTANCE;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFileType.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFileType.java
new file mode 100644 (file)
index 0000000..0cc8f8b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.ui.LayeredIcon;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class RegExpFileType extends LanguageFileType {
+    public static final RegExpFileType INSTANCE = new RegExpFileType();
+
+    private final Icon myIcon;
+
+    private RegExpFileType() {
+        super(RegExpLanguage.INSTANCE);
+
+        myIcon = new LayeredIcon(2);
+        ((LayeredIcon)myIcon).setIcon(IconLoader.getIcon("/fileTypes/text.png"), 0);
+        ((LayeredIcon)myIcon).setIcon(IconLoader.getIcon("regexp-filetype-icon.png"), 1);
+
+//        myIcon = LayeredIcon.create(
+//                IconLoader.getIcon("/fileTypes/text.png"),
+//                IconLoader.getIcon("regexp-filetype-icon.png"));
+    }
+
+    @NotNull
+    @NonNls
+    public String getName() {
+        return "RegExp";
+    }
+
+    @NotNull
+    public String getDescription() {
+        return "Regular Expression";
+    }
+
+    @NotNull
+    @NonNls
+    public String getDefaultExtension() {
+        return "regexp";
+    }
+
+    @Nullable
+    public Icon getIcon() {
+        return myIcon;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java
new file mode 100644 (file)
index 0000000..61f2613
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.HighlighterColors;
+import com.intellij.openapi.editor.SyntaxHighlighterColors;
+import com.intellij.openapi.editor.JavaHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.StringEscapesTokenTypes;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class RegExpHighlighter extends SyntaxHighlighterBase {
+    private static Map<IElementType, TextAttributesKey> keys1;
+    private static Map<IElementType, TextAttributesKey> keys2;
+
+    static final TextAttributesKey META = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.META",
+            SyntaxHighlighterColors.KEYWORD.getDefaultAttributes()
+    );
+    static final TextAttributesKey INVALID_CHARACTER_ESCAPE = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.INVALID_STRING_ESCAPE",
+            JavaHighlighterColors.JAVA_INVALID_STRING_ESCAPE.getDefaultAttributes()
+    );
+    static final TextAttributesKey BAD_CHARACTER = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.BAD_CHARACTER",
+            HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
+    );
+    static final TextAttributesKey REDUNDANT_ESCAPE = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.REDUNDANT_ESCAPE",
+            JavaHighlighterColors.JAVA_VALID_STRING_ESCAPE.getDefaultAttributes()
+    );
+    static final TextAttributesKey PARENTHS = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.PARENTHS",
+            SyntaxHighlighterColors.PARENTHS.getDefaultAttributes()
+    );
+    static final TextAttributesKey BRACES = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.BRACES",
+            SyntaxHighlighterColors.BRACES.getDefaultAttributes()
+    );
+    static final TextAttributesKey BRACKETS = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.BRACKETS",
+            SyntaxHighlighterColors.BRACKETS.getDefaultAttributes()
+    );
+    static final TextAttributesKey COMMA = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.COMMA",
+            SyntaxHighlighterColors.COMMA.getDefaultAttributes()
+    );
+    static final TextAttributesKey ESC_CHARACTER = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.ESC_CHARACTER",
+            JavaHighlighterColors.JAVA_VALID_STRING_ESCAPE.getDefaultAttributes()
+    );
+    static final TextAttributesKey CHAR_CLASS = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.CHAR_CLASS",
+            JavaHighlighterColors.JAVA_VALID_STRING_ESCAPE.getDefaultAttributes()
+    );
+    static final TextAttributesKey QUOTE_CHARACTER = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.QUOTE_CHARACTER",
+            JavaHighlighterColors.JAVA_VALID_STRING_ESCAPE.getDefaultAttributes()
+    );
+    static final TextAttributesKey CTRL_CHARACTER = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.CTRL_CHARACTER",
+            HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
+    );
+    static final TextAttributesKey COMMENT = TextAttributesKey.createTextAttributesKey(
+            "REGEXP.COMMENT",
+            SyntaxHighlighterColors.LINE_COMMENT.getDefaultAttributes()
+    );
+
+    private final Project myProject;
+    private final ParserDefinition myParserDefinition;
+
+    public RegExpHighlighter(Project project, ParserDefinition parserDefinition) {
+        myProject = project;
+        myParserDefinition = parserDefinition;
+    }
+
+    static {
+        keys1 = new HashMap<IElementType, TextAttributesKey>();
+        keys2 = new HashMap<IElementType, TextAttributesKey>();
+
+        fillMap(keys1, RegExpTT.KEYWORDS, META);
+
+        keys1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, INVALID_CHARACTER_ESCAPE);
+        keys1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, INVALID_CHARACTER_ESCAPE);
+
+        keys1.put(TokenType.BAD_CHARACTER, BAD_CHARACTER);
+        keys1.put(RegExpTT.BAD_HEX_VALUE, INVALID_CHARACTER_ESCAPE);
+        keys1.put(RegExpTT.BAD_OCT_VALUE, INVALID_CHARACTER_ESCAPE);
+
+        keys1.put(RegExpTT.CTRL_CHARACTER, CTRL_CHARACTER);
+        keys1.put(RegExpTT.PROPERTY, CHAR_CLASS);
+
+        keys1.put(RegExpTT.ESC_CHARACTER, ESC_CHARACTER);
+        keys1.put(RegExpTT.UNICODE_CHAR, ESC_CHARACTER);
+        keys1.put(RegExpTT.HEX_CHAR, ESC_CHARACTER);
+        keys1.put(RegExpTT.OCT_CHAR, ESC_CHARACTER);
+        keys1.put(RegExpTT.CHAR_CLASS, ESC_CHARACTER);
+        keys1.put(RegExpTT.BOUNDARY, ESC_CHARACTER);
+        keys1.put(RegExpTT.CTRL, ESC_CHARACTER);
+        keys1.put(RegExpTT.ESC_CTRL_CHARACTER, ESC_CHARACTER);
+
+        keys1.put(RegExpTT.REDUNDANT_ESCAPE, REDUNDANT_ESCAPE);
+
+        keys1.put(RegExpTT.QUOTE_BEGIN, QUOTE_CHARACTER);
+        keys1.put(RegExpTT.QUOTE_END, QUOTE_CHARACTER);
+
+        keys1.put(RegExpTT.GROUP_BEGIN, PARENTHS);
+        keys1.put(RegExpTT.GROUP_END, PARENTHS);
+
+        keys1.put(RegExpTT.LBRACE, BRACES);
+        keys1.put(RegExpTT.RBRACE, BRACES);
+
+        keys1.put(RegExpTT.CLASS_BEGIN, BRACKETS);
+        keys1.put(RegExpTT.CLASS_END, BRACKETS);
+
+        keys1.put(RegExpTT.COMMA, COMMA);
+
+        keys1.put(RegExpTT.COMMENT, COMMENT);
+    }
+
+    @NotNull
+    public Lexer getHighlightingLexer() {
+        return myParserDefinition.createLexer(myProject);
+    }
+
+    @NotNull
+    public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+        return pack(keys1.get(tokenType), keys2.get(tokenType));
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguage.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguage.java
new file mode 100644 (file)
index 0000000..6decdbe
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.lang.BracePair;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageAnnotators;
+import com.intellij.lang.LanguageBraceMatching;
+import com.intellij.lang.LanguageDocumentation;
+import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.lang.LanguageSurrounders;
+import com.intellij.lang.PairedBraceMatcher;
+import com.intellij.lang.documentation.QuickDocumentationProvider;
+import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.tree.IElementType;
+import org.intellij.lang.regexp.psi.RegExpGroup;
+import org.intellij.lang.regexp.psi.impl.RegExpElementImpl;
+import org.intellij.lang.regexp.surroundWith.SimpleSurroundDescriptor;
+import org.intellij.lang.regexp.validation.RegExpAnnotator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class RegExpLanguage extends Language {
+    public static final RegExpLanguage INSTANCE = new RegExpLanguage();
+
+    protected RegExpLanguage() {
+        super("RegExp");
+        final RegExpParserDefinition parserDefinition = new RegExpParserDefinition();
+
+        LanguageAnnotators.INSTANCE.addExpicitExtension(this, new RegExpAnnotator());
+        LanguageParserDefinitions.INSTANCE.addExpicitExtension(this, parserDefinition);
+        LanguageBraceMatching.INSTANCE.addExpicitExtension(this, createPairedBraceMatcher());
+        LanguageSurrounders.INSTANCE.addExpicitExtension(this, new SimpleSurroundDescriptor());
+        SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExpicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
+            @NotNull
+            protected SyntaxHighlighter createHighlighter() {
+                return new RegExpHighlighter(null, parserDefinition);
+            }
+        });
+
+        LanguageDocumentation.INSTANCE.addExpicitExtension(this, new QuickDocumentationProvider() {
+            @Nullable
+            public String getQuickNavigateInfo(PsiElement element) {
+                if (element instanceof RegExpGroup) {
+                    return "Capturing Group: " + ((RegExpElementImpl)element).getUnescapedText();
+                } else {
+                    return null;
+                }
+            }
+        });
+    }
+
+    @NotNull
+    private static PairedBraceMatcher createPairedBraceMatcher() {
+        return new PairedBraceMatcher() {
+            public BracePair[] getPairs() {
+                return new BracePair[]{
+                        new BracePair(RegExpTT.GROUP_BEGIN, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.SET_OPTIONS, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.NON_CAPT_GROUP, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.POS_LOOKAHEAD, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.NEG_LOOKAHEAD, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.POS_LOOKBEHIND, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.NEG_LOOKBEHIND, RegExpTT.GROUP_END, true),
+                        new BracePair(RegExpTT.CLASS_BEGIN, RegExpTT.CLASS_END, false),
+                        new BracePair(RegExpTT.LBRACE, RegExpTT.RBRACE, false),
+                        new BracePair(RegExpTT.QUOTE_BEGIN, RegExpTT.QUOTE_END, false),
+                };
+            }
+
+            public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType contextType) {
+                return false;
+            }
+
+            public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
+                return openingBraceOffset;
+            }
+        };
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java
new file mode 100644 (file)
index 0000000..82edb32
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.lexer.FlexAdapter;
+
+class RegExpLexer extends FlexAdapter {
+
+    private static final int COMMENT_MODE = 1 << 14;
+
+    public RegExpLexer(boolean xmlSchemaMode) {
+        super(new _RegExLexer(xmlSchemaMode));
+    }
+
+    public void start(char[] buffer, int startOffset, int endOffset, int initialState) {
+        getFlex().commentMode = (initialState & COMMENT_MODE) != 0;
+        initialState = initialState & ~COMMENT_MODE;
+        super.start(buffer, startOffset, endOffset, initialState);
+    }
+
+    public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
+        getFlex().commentMode = (initialState & COMMENT_MODE) != 0;
+        initialState = initialState & ~COMMENT_MODE;
+        super.start(buffer, startOffset, endOffset, initialState);
+    }
+
+    public _RegExLexer getFlex() {
+        return (_RegExLexer)super.getFlex();
+    }
+
+    public int getState() {
+        final boolean commentMode = getFlex().commentMode;
+        final int state = super.getState();
+        return commentMode ? state | COMMENT_MODE : state;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java
new file mode 100644 (file)
index 0000000..df79230
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@SuppressWarnings({ "RedundantIfStatement" })
+class RegExpParser implements PsiParser {
+    @NotNull
+    public ASTNode parse(IElementType root, PsiBuilder builder) {
+//        builder.setDebugMode(true);
+        final PsiBuilder.Marker rootMarker = builder.mark();
+
+        parsePattern(builder);
+
+        while (!builder.eof()) {
+            patternExpected(builder);
+            builder.advanceLexer();
+        }
+
+        rootMarker.done(root);
+        return builder.getTreeBuilt();
+    }
+
+
+    /**
+     * PATTERN ::= BRANCH "|" PATTERN | BRANCH
+     */
+    private boolean parsePattern(PsiBuilder builder) {
+        final PsiBuilder.Marker marker = builder.mark();
+
+        if (!parseBranch(builder)) {
+            marker.drop();
+            return false;
+        }
+
+        while (builder.getTokenType() == RegExpTT.UNION) {
+            builder.advanceLexer();
+            if (!parseBranch(builder)) {
+                // TODO: no test coverage
+                patternExpected(builder);
+                break;
+            }
+        }
+
+        marker.done(RegExpElementTypes.PATTERN);
+
+        return true;
+    }
+
+    /**
+     * BRANCH  ::= ATOM BRANCH | ""
+     */
+    @SuppressWarnings({ "StatementWithEmptyBody" })
+    private boolean parseBranch(PsiBuilder builder) {
+        PsiBuilder.Marker marker = builder.mark();
+
+        if (!parseAtom(builder)) {
+            final IElementType token = builder.getTokenType();
+            if (token == RegExpTT.GROUP_END || token == RegExpTT.UNION || token == null) {
+                // empty branches are allowed
+                marker.done(RegExpElementTypes.BRANCH);
+                return true;
+            }
+            marker.drop();
+            return false;
+        }
+
+        for (;parseAtom(builder);) ;
+
+        marker.done(RegExpElementTypes.BRANCH);
+        return true;
+    }
+
+    /**
+     * ATOM        ::= CLOSURE | GROUP
+     * CLOSURE     ::= GROUP QUANTIFIER
+     */
+    private boolean parseAtom(PsiBuilder builder) {
+        PsiBuilder.Marker marker = parseGroup(builder);
+
+        if (marker == null) {
+            return false;
+        }
+        marker = marker.precede();
+
+        if (parseQuantifier(builder)) {
+            marker.done(RegExpElementTypes.CLOSURE);
+        } else {
+            marker.drop();
+        }
+
+        return true;
+    }
+
+    /**
+     * QUANTIFIER   ::= Q TYPE | ""
+     * Q            ::= "{" BOUND "}" | "*" | "?" | "+"
+     * BOUND        ::= NUM | NUM "," | NUM "," NUM
+     * TYPE         ::= "?" | "+" | ""
+     */
+    private boolean parseQuantifier(PsiBuilder builder) {
+        final PsiBuilder.Marker marker = builder.mark();
+
+        if (builder.getTokenType() == RegExpTT.LBRACE) {
+            builder.advanceLexer();
+            checkMatches(builder, RegExpTT.NUMBER, "Number expected");
+            if (builder.getTokenType() == RegExpTT.RBRACE) {
+                builder.advanceLexer();
+                parseQuantifierType(builder);
+                marker.done(RegExpElementTypes.QUANTIFIER);
+            } else {
+                checkMatches(builder, RegExpTT.COMMA, "',' expected");
+                if (builder.getTokenType() == RegExpTT.RBRACE) {
+                    builder.advanceLexer();
+                    parseQuantifierType(builder);
+                    marker.done(RegExpElementTypes.QUANTIFIER);
+                } else if (builder.getTokenType() == RegExpTT.NUMBER) {
+                    builder.advanceLexer();
+                    checkMatches(builder, RegExpTT.RBRACE, "'}' expected");
+                    parseQuantifierType(builder);
+                    marker.done(RegExpElementTypes.QUANTIFIER);
+                } else {
+                    builder.error("'}' or number expected");
+                    marker.done(RegExpElementTypes.QUANTIFIER);
+                    return true;
+                }
+            }
+        } else if (RegExpTT.QUANTIFIERS.contains(builder.getTokenType())) {
+            builder.advanceLexer();
+            parseQuantifierType(builder);
+            marker.done(RegExpElementTypes.QUANTIFIER);
+        } else {
+            marker.drop();
+            return false;
+        }
+
+        return true;
+    }
+
+    private void parseQuantifierType(PsiBuilder builder) {
+        if (builder.getTokenType() == RegExpTT.PLUS) {
+            builder.advanceLexer();
+        } else if (builder.getTokenType() == RegExpTT.QUEST) {
+            builder.advanceLexer();
+        } else {
+            if (RegExpTT.QUANTIFIERS.contains(builder.getTokenType())) {
+                builder.advanceLexer();
+                builder.error("Dangling metacharacter");
+            }
+        }
+    }
+
+    /**
+     * CLASS            ::= "[" NEGATION DEFLIST "]"
+     * NEGATION         ::= "^" | ""
+     * DEFLIST          ::= INTERSECTION DEFLIST
+     * INTERSECTION     ::= INTERSECTION "&&" CLASSDEF | CLASSDEF
+     * CLASSDEF         ::= CLASS | SIMPLE_CLASSDEF | ""
+     * SIMPLE_CLASSDEF  ::= CHARACTER | CHARACTER "-" CLASSDEF
+     */
+    private PsiBuilder.Marker parseClass(PsiBuilder builder) {
+        final PsiBuilder.Marker marker = builder.mark();
+        builder.advanceLexer();
+
+        if (builder.getTokenType() == RegExpTT.CARET) {
+            builder.advanceLexer();
+        }
+
+        // DEFLIST
+        if (parseClassIntersection(builder)) {
+            while (RegExpTT.CHARACTERS2.contains(builder.getTokenType())
+                    || builder.getTokenType() == RegExpTT.CLASS_BEGIN
+                    || builder.getTokenType() == RegExpTT.PROPERTY) 
+            {
+                parseClassIntersection(builder);
+            }
+        }
+
+        checkMatches(builder, RegExpTT.CLASS_END, "Unclosed character class");
+        marker.done(RegExpElementTypes.CLASS);
+        return marker;
+    }
+
+    private boolean parseClassIntersection(PsiBuilder builder) {
+        PsiBuilder.Marker marker = builder.mark();
+
+        if (!parseClassdef(builder, false)) {
+            marker.drop();
+            return false;
+        }
+        while (RegExpTT.ANDAND == builder.getTokenType()) {
+            builder.advanceLexer();
+            parseClassdef(builder, true);
+            marker.done(RegExpElementTypes.INTERSECTION);
+            marker = marker.precede();
+        }
+
+        marker.drop();
+        return true;
+    }
+
+    private boolean parseClassdef(PsiBuilder builder, boolean mayBeEmpty) {
+        final IElementType token = builder.getTokenType();
+        if (token == RegExpTT.CLASS_BEGIN) {
+            parseClass(builder);
+        } else if (RegExpTT.CHARACTERS2.contains(token)) {
+            parseSimpleClassdef(builder);
+        } else if (token == RegExpTT.PROPERTY) {
+            parseProperty(builder);
+        } else if (mayBeEmpty) {
+            // TODO: no test coverage
+            return true;
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    private void parseSimpleClassdef(PsiBuilder builder) {
+        assert RegExpTT.CHARACTERS2.contains(builder.getTokenType());
+
+        final PsiBuilder.Marker marker = builder.mark();
+        makeChar(builder);
+
+        IElementType t = builder.getTokenType();
+        if (t == RegExpTT.MINUS) {
+            final PsiBuilder.Marker m = builder.mark();
+            builder.advanceLexer();
+
+            t = builder.getTokenType();
+            if (RegExpTT.CHARACTERS2.contains(t)) {
+                m.drop();
+                makeChar(builder);
+                marker.done(RegExpElementTypes.CHAR_RANGE);
+            } else {
+                marker.drop();
+                m.done(t == RegExpTT.CHAR_CLASS ?
+                        RegExpElementTypes.SIMPLE_CLASS :
+                        RegExpElementTypes.CHAR);
+
+                if (t == RegExpTT.CLASS_END) { // [a-]
+                    return;
+                } else if (t == RegExpTT.CLASS_BEGIN) { // [a-[b]]
+                    if (parseClassdef(builder, false)) {
+                        return;
+                    }
+                }
+                builder.error("Illegal character range");
+            }
+        } else {
+            marker.drop();
+        }
+    }
+
+    private static void makeChar(PsiBuilder builder) {
+        final IElementType t = builder.getTokenType();
+        PsiBuilder.Marker m = builder.mark();
+        builder.advanceLexer();
+        m.done(t == RegExpTT.CHAR_CLASS ?
+                        RegExpElementTypes.SIMPLE_CLASS :
+                        RegExpElementTypes.CHAR);
+    }
+
+    /**
+     * GROUP  ::= "(" PATTERN ")" | TERM
+     * TERM   ::= "." | "$" | "^" | CHAR | CLASS | BACKREF
+     */
+    @Nullable
+    private PsiBuilder.Marker parseGroup(PsiBuilder builder) {
+        final IElementType type = builder.getTokenType();
+
+        final PsiBuilder.Marker marker = builder.mark();
+        if (RegExpTT.GROUPS.contains(type)) {
+            builder.advanceLexer();
+            if (!parsePattern(builder)) {
+                patternExpected(builder);
+            } else {
+                checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group");
+            }
+            marker.done(RegExpElementTypes.GROUP);
+        } else if (type == RegExpTT.SET_OPTIONS) {
+            builder.advanceLexer();
+
+            final PsiBuilder.Marker o = builder.mark();
+            if (builder.getTokenType() == RegExpTT.OPTIONS_ON) {
+                builder.advanceLexer();
+            }
+            if (builder.getTokenType() == RegExpTT.OPTIONS_OFF) {
+                builder.advanceLexer();
+            }
+            o.done(RegExpElementTypes.OPTIONS);
+
+            if (builder.getTokenType() == RegExpTT.COLON) {
+                builder.advanceLexer();
+                if (!parsePattern(builder)) {
+                    // TODO: no test coverage
+                    patternExpected(builder);
+                } else {
+                    checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group");
+                }
+                marker.done(RegExpElementTypes.GROUP);
+            } else {
+                checkMatches(builder, RegExpTT.GROUP_END, "Unclosed options group");
+                marker.done(RegExpElementTypes.SET_OPTIONS);
+            }
+        } else if (RegExpTT.CHARACTERS.contains(type)) {
+            builder.advanceLexer();
+            marker.done(RegExpElementTypes.CHAR);
+        } else if (RegExpTT.BOUNDARIES.contains(type)) {
+            builder.advanceLexer();
+            marker.done(RegExpElementTypes.BOUNDARY);
+        } else if (type == RegExpTT.BACKREF) {
+            builder.advanceLexer();
+            marker.done(RegExpElementTypes.BACKREF);
+        } else if (type == RegExpTT.PROPERTY) {
+            parseProperty(builder);
+            marker.done(RegExpElementTypes.PROPERTY);
+        } else if (RegExpTT.SIMPLE_CLASSES.contains(type)) {
+            builder.advanceLexer();
+            marker.done(RegExpElementTypes.SIMPLE_CLASS);
+        } else if (type == RegExpTT.CLASS_BEGIN) {
+            marker.drop();
+            return parseClass(builder);
+        } else {
+            marker.drop();
+            return null;
+        }
+        return marker;
+    }
+
+    private void parseProperty(PsiBuilder builder) {
+        checkMatches(builder, RegExpTT.PROPERTY, "'\\p' expected");
+
+        checkMatches(builder, RegExpTT.LBRACE, "Character category expected");
+        if (builder.getTokenType() == RegExpTT.NAME) {
+            builder.advanceLexer();
+        } else if (builder.getTokenType() == RegExpTT.RBRACE) {
+            builder.error("Empty character family");
+        } else {
+            builder.error("Character family name expected");
+            builder.advanceLexer();
+        }
+        checkMatches(builder, RegExpTT.RBRACE, "Unclosed character family");
+    }
+
+    private static void patternExpected(PsiBuilder builder) {
+        final IElementType token = builder.getTokenType();
+        if (token == RegExpTT.GROUP_END) {
+            builder.advanceLexer();
+            builder.error("Unmatched closing ')'");
+        } else if (RegExpTT.QUANTIFIERS.contains(token)) {
+            builder.advanceLexer();
+            builder.error("Dangling metacharacter");
+        } else {
+            builder.error("Pattern expected");
+        }
+    }
+
+    protected static void checkMatches(final PsiBuilder builder, final IElementType token, final String message) {
+        if (builder.getTokenType() == token) {
+            builder.advanceLexer();
+        } else {
+            builder.error(message);
+        }
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java
new file mode 100644 (file)
index 0000000..e5c9fe9
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lang.ASTNode;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.TokenType;
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.psi.impl.*;
+
+class RegExpParserDefinition implements ParserDefinition {
+    @NotNull
+    public Lexer createLexer(Project project) {
+        return new RegExpLexer(false);
+    }
+
+    public PsiParser createParser(Project project) {
+        return new RegExpParser();
+    }
+
+    public IFileElementType getFileNodeType() {
+        return RegExpElementTypes.REGEXP_FILE;
+    }
+
+    @NotNull
+    public TokenSet getWhitespaceTokens() {
+        // trick to hide quote tokens from parser... should actually go into the lexer
+        return TokenSet.create(RegExpTT.QUOTE_BEGIN, RegExpTT.QUOTE_END, TokenType.WHITE_SPACE);
+    }
+
+    @NotNull
+    public TokenSet getStringLiteralElements() {
+        return TokenSet.EMPTY;
+    }
+
+    @NotNull
+    public TokenSet getCommentTokens() {
+        return TokenSet.create(RegExpTT.COMMENT);
+    }
+
+    @NotNull
+    public PsiElement createElement(ASTNode node) {
+        final IElementType type = node.getElementType();
+        if (type == RegExpElementTypes.PATTERN) {
+            return new RegExpPatternImpl(node);
+        } else if (type == RegExpElementTypes.BRANCH) {
+            return new RegExpBranchImpl(node);
+        } else if (type == RegExpElementTypes.SIMPLE_CLASS) {
+            return new RegExpSimpleClassImpl(node);
+        } else if (type == RegExpElementTypes.CLASS) {
+            return new RegExpClassImpl(node);
+        } else if (type == RegExpElementTypes.CHAR_RANGE) {
+            return new RegExpCharRangeImpl(node);
+        } else if (type == RegExpElementTypes.CHAR) {
+            return new RegExpCharImpl(node);
+        } else if (type == RegExpElementTypes.GROUP) {
+            return new RegExpGroupImpl(node);
+        } else if (type == RegExpElementTypes.PROPERTY) {
+            return new RegExpPropertyImpl(node);
+        } else if (type == RegExpElementTypes.SET_OPTIONS) {
+            return new RegExpSetOptionsImpl(node);
+        } else if (type == RegExpElementTypes.OPTIONS) {
+            return new RegExpOptionsImpl(node);
+        } else if (type == RegExpElementTypes.BACKREF) {
+            return new RegExpBackrefImpl(node);
+        } else if (type == RegExpElementTypes.CLOSURE) {
+            return new RegExpClosureImpl(node);
+        } else if (type == RegExpElementTypes.QUANTIFIER) {
+            return new RegExpQuantifierImpl(node);
+        } else if (type == RegExpElementTypes.BOUNDARY) {
+            return new RegExpBoundaryImpl(node);
+        } else if (type == RegExpElementTypes.INTERSECTION) {
+            return new RegExpIntersectionImpl(node);
+        }
+        return new ASTWrapperPsiElement(node);
+    }
+
+    public PsiFile createFile(FileViewProvider viewProvider) {
+        return new RegExpFile(viewProvider);
+    }
+
+    public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+        return SpaceRequirements.MUST_NOT;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpSupportLoader.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpSupportLoader.java
new file mode 100644 (file)
index 0000000..4ba1f1c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.intellij.lang.regexp;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import org.jetbrains.annotations.NotNull;
+
+public class RegExpSupportLoader implements ApplicationComponent {
+    // should be true unless verified fix for IDEADEV-10862 is available 
+    private static final boolean DBG_MODE = true || Boolean.getBoolean("regexp-lang.register-file-type");
+
+    public static final RegExpLanguage LANGUAGE = RegExpLanguage.INSTANCE;
+    public static final RegExpFileType FILE_TYPE = RegExpFileType.INSTANCE;
+
+    public void initComponent() {
+        if (DBG_MODE) {
+            ApplicationManager.getApplication().runWriteAction(new Runnable() {
+                public void run() {
+                    final String[] extensions = new String[]{ FILE_TYPE.getDefaultExtension() };
+                    FileTypeManager.getInstance().registerFileType(FILE_TYPE, extensions);
+                }
+            });
+        }
+    }
+
+    public void disposeComponent() {
+    }
+
+    @NotNull
+    public String getComponentName() {
+        return "RegExpSupportLoader";
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpTT.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpTT.java
new file mode 100644 (file)
index 0000000..f0958ab
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.StringEscapesTokenTypes;
+
+public interface RegExpTT {
+    IElementType NUMBER = new RegExpElementType("NUMBER");
+    IElementType NAME = new RegExpElementType("NAME");
+    IElementType COMMA = new RegExpElementType("COMMA");
+
+    // "\\Q"
+    IElementType QUOTE_BEGIN = new RegExpElementType("QUOTE_BEGIN");
+    // <QUOTE> "\\E"
+    IElementType QUOTE_END = new RegExpElementType("QUOTE_END");
+
+    // "\\" 0-9
+    IElementType BACKREF = new RegExpElementType("BACKREF");
+
+    IElementType LBRACE = new RegExpElementType("LBRACE");
+    IElementType RBRACE = new RegExpElementType("RBRACE");
+
+    IElementType CLASS_BEGIN = new RegExpElementType("CLASS_BEGIN");
+    IElementType CLASS_END = new RegExpElementType("CLASS_END");
+    IElementType ANDAND = new RegExpElementType("ANDAND");
+
+    IElementType GROUP_BEGIN = new RegExpElementType("GROUP_BEGIN");
+    IElementType GROUP_END = new RegExpElementType("GROUP_END");
+
+    IElementType NON_CAPT_GROUP = new RegExpElementType("NON_CAPT_GROUP");
+    IElementType POS_LOOKBEHIND = new RegExpElementType("POS_LOOKBEHIND");
+    IElementType NEG_LOOKBEHIND = new RegExpElementType("NEG_LOOKBEHIND");
+    IElementType POS_LOOKAHEAD = new RegExpElementType("POS_LOOKAHEAD");
+    IElementType NEG_LOOKAHEAD = new RegExpElementType("NEG_LOOKAHEAD");
+    IElementType SET_OPTIONS = new RegExpElementType("SET_OPTIONS");
+
+    IElementType QUEST = new RegExpElementType("QUEST");
+    IElementType STAR = new RegExpElementType("STAR");
+    IElementType PLUS = new RegExpElementType("PLUS");
+    IElementType COLON = new RegExpElementType("COLON");
+
+    // "\\" ("b" | "B" | "A" | "z" | "Z" | "G")
+    IElementType BOUNDARY = new RegExpElementType("BOUNDARY");
+    // "^"
+    IElementType CARET = new RegExpElementType("CARET");
+    // "$"
+    IElementType DOLLAR = new RegExpElementType("DOLLAR");
+
+    IElementType DOT = new RegExpElementType("DOT");
+    IElementType UNION = new RegExpElementType("UNION");
+
+    // "\b" | "\t" | "\f" | "\r" | "\n"
+    IElementType CTRL_CHARACTER = new RegExpElementType("CTRL_CHARACTER");
+    // "\\" ("t" | "n" | "r" | "f" | "a" | "e")
+    IElementType ESC_CTRL_CHARACTER = new RegExpElementType("ESC_CTRL_CHARACTER");
+    // "\\" ("." | "|" | "$" | "^" | "?" | "*" | "+" | "[" | "{" | "(" | ")")
+    IElementType ESC_CHARACTER = new RegExpElementType("ESC_CHARACTER");
+    // "\\" ("w" | "W" | "s" | "S" | "d" | "D")
+    IElementType CHAR_CLASS = new RegExpElementType("CHAR_CLASS");
+    // "\\u" XXXX
+    IElementType UNICODE_CHAR = new RegExpElementType("UNICODE_CHAR");
+    // "\\x" XX
+    IElementType HEX_CHAR = new RegExpElementType("HEX_CHAR");
+    // "\\0" OOO
+    IElementType OCT_CHAR = new RegExpElementType("OCT_CHAR");
+    // "\\c" x
+    IElementType CTRL = new RegExpElementType("CTRL");
+    // "\\p" | "\\P"
+    IElementType PROPERTY = new RegExpElementType("PROPERTY");
+
+    // e.g. "\\#" but also "\\q" which is not a valid escape actually
+    IElementType REDUNDANT_ESCAPE = new RegExpElementType("REDUNDANT_ESCAPE");
+
+    IElementType MINUS = new RegExpElementType("MINUS");
+    IElementType CHARACTER = new RegExpElementType("CHARACTER");
+
+    IElementType BAD_CHARACTER = new RegExpElementType("BAD_CHARACTER");
+    IElementType BAD_OCT_VALUE = new RegExpElementType("BAD_OCT_VALUE");
+    IElementType BAD_HEX_VALUE = new RegExpElementType("BAD_HEX_VALUE");
+
+    IElementType COMMENT = new RegExpElementType("COMMENT");
+    IElementType OPTIONS_ON = new RegExpElementType("OPTIONS_ON");
+    IElementType OPTIONS_OFF = new RegExpElementType("OPTIONS_OFF");
+
+    TokenSet KEYWORDS = TokenSet.create(DOT, STAR, QUEST, PLUS);
+
+    TokenSet CHARACTERS = TokenSet.create(CHARACTER,
+            ESC_CTRL_CHARACTER,
+            ESC_CHARACTER,
+            CTRL_CHARACTER,
+            UNICODE_CHAR,
+            HEX_CHAR, BAD_HEX_VALUE,
+            OCT_CHAR, BAD_OCT_VALUE,
+            REDUNDANT_ESCAPE,
+            MINUS,
+            StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN,
+            StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
+
+    TokenSet SIMPLE_CLASSES = TokenSet.create(DOT, CHAR_CLASS);
+
+    // caret is just a character in classes after the first position: [a^] matches "a" or "^"
+    TokenSet CHARACTERS2 = TokenSet.orSet(CHARACTERS, SIMPLE_CLASSES, TokenSet.create(CARET));
+
+    TokenSet QUANTIFIERS = TokenSet.create(QUEST, PLUS, STAR, LBRACE);
+
+    TokenSet GROUPS = TokenSet.create(GROUP_BEGIN,
+            NON_CAPT_GROUP,
+            POS_LOOKAHEAD,
+            NEG_LOOKAHEAD,
+            POS_LOOKBEHIND,
+            NEG_LOOKBEHIND);
+
+    TokenSet BOUNDARIES = TokenSet.create(BOUNDARY, CARET, DOLLAR);
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java
new file mode 100644 (file)
index 0000000..60ed2ea
--- /dev/null
@@ -0,0 +1,863 @@
+/* The following code was generated by JFlex 1.4.1 on 10.12.07 20:08 */
+
+/* It's an automatically generated code. Do not modify it. */
+package org.intellij.lang.regexp;
+
+import com.intellij.lexer.FlexLexer;
+import com.intellij.psi.tree.IElementType;
+import java.util.LinkedList;
+import com.intellij.psi.StringEscapesTokenTypes;
+
+// IDEADEV-11055
+@SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" })
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.1
+ * on 10.12.07 20:08 from the specification file
+ * <tt>C:/work/java/idea-plugins/IntelliLang/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
+ */
+class _RegExLexer implements FlexLexer {
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 16384;
+
+  /** lexical states */
+  public static final int CLASS1 = 3;
+  public static final int EMBRACED = 2;
+  public static final int QUOTED = 1;
+  public static final int YYINITIAL = 0;
+  public static final int COMMENT = 6;
+  public static final int OPTIONS = 5;
+  public static final int CLASS2 = 4;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\10\0\2\56\1\13\1\0\1\56\1\54\22\0\1\55\1\51\1\0"+
+    "\1\53\1\15\1\0\1\46\1\0\1\4\1\5\1\17\1\20\1\45"+
+    "\1\42\1\3\1\0\1\2\7\41\2\1\1\47\1\0\1\52\1\50"+
+    "\1\0\1\16\1\0\1\24\1\24\1\30\1\27\1\36\1\34\1\25"+
+    "\1\43\1\32\6\43\1\33\1\35\1\43\1\26\3\43\1\26\1\26"+
+    "\1\43\1\25\1\10\1\12\1\11\1\14\2\0\1\23\1\24\1\31"+
+    "\1\27\1\23\1\23\2\43\1\32\4\43\1\22\1\43\1\33\1\43"+
+    "\1\22\1\26\1\22\1\40\1\43\1\26\1\37\1\43\1\25\1\6"+
+    "\1\21\1\7\54\0\1\43\12\0\1\43\4\0\1\43\5\0\27\43"+
+    "\1\0\37\43\1\0\u013f\43\31\0\162\43\4\0\14\43\16\0\5\43"+
+    "\11\0\1\43\213\0\1\43\13\0\1\43\1\0\3\43\1\0\1\43"+
+    "\1\0\24\43\1\0\54\43\1\0\46\43\1\0\5\43\4\0\202\43"+
+    "\10\0\105\43\1\0\46\43\2\0\2\43\6\0\20\43\41\0\46\43"+
+    "\2\0\1\43\7\0\47\43\110\0\33\43\5\0\3\43\56\0\32\43"+
+    "\5\0\13\43\25\0\12\44\4\0\2\43\1\0\143\43\1\0\1\43"+
+    "\17\0\2\43\7\0\2\43\12\44\3\43\2\0\1\43\20\0\1\43"+
+    "\1\0\36\43\35\0\3\43\60\0\46\43\13\0\1\43\u0152\0\66\43"+
+    "\3\0\1\43\22\0\1\43\7\0\12\43\4\0\12\44\25\0\10\43"+
+    "\2\0\2\43\2\0\26\43\1\0\7\43\1\0\1\43\3\0\4\43"+
+    "\3\0\1\43\36\0\2\43\1\0\3\43\4\0\12\44\2\43\23\0"+
+    "\6\43\4\0\2\43\2\0\26\43\1\0\7\43\1\0\2\43\1\0"+
+    "\2\43\1\0\2\43\37\0\4\43\1\0\1\43\7\0\12\44\2\0"+
+    "\3\43\20\0\11\43\1\0\3\43\1\0\26\43\1\0\7\43\1\0"+
+    "\2\43\1\0\5\43\3\0\1\43\22\0\1\43\17\0\2\43\4\0"+
+    "\12\44\25\0\10\43\2\0\2\43\2\0\26\43\1\0\7\43\1\0"+
+    "\2\43\1\0\5\43\3\0\1\43\36\0\2\43\1\0\3\43\4\0"+
+    "\12\44\1\0\1\43\21\0\1\43\1\0\6\43\3\0\3\43\1\0"+
+    "\4\43\3\0\2\43\1\0\1\43\1\0\2\43\3\0\2\43\3\0"+
+    "\3\43\3\0\10\43\1\0\3\43\55\0\11\44\25\0\10\43\1\0"+
+    "\3\43\1\0\27\43\1\0\12\43\1\0\5\43\46\0\2\43\4\0"+
+    "\12\44\25\0\10\43\1\0\3\43\1\0\27\43\1\0\12\43\1\0"+
+    "\5\43\3\0\1\43\40\0\1\43\1\0\2\43\4\0\12\44\25\0"+
+    "\10\43\1\0\3\43\1\0\27\43\1\0\20\43\46\0\2\43\4\0"+
+    "\12\44\25\0\22\43\3\0\30\43\1\0\11\43\1\0\1\43\2\0"+
+    "\7\43\72\0\60\43\1\0\2\43\14\0\7\43\11\0\12\44\47\0"+
+    "\2\43\1\0\1\43\2\0\2\43\1\0\1\43\2\0\1\43\6\0"+
+    "\4\43\1\0\7\43\1\0\3\43\1\0\1\43\1\0\1\43\2\0"+
+    "\2\43\1\0\4\43\1\0\2\43\11\0\1\43\2\0\5\43\1\0"+
+    "\1\43\11\0\12\44\2\0\2\43\42\0\1\43\37\0\12\44\26\0"+
+    "\10\43\1\0\42\43\35\0\4\43\164\0\42\43\1\0\5\43\1\0"+
+    "\2\43\25\0\12\44\6\0\6\43\112\0\46\43\12\0\51\43\7\0"+
+    "\132\43\5\0\104\43\5\0\122\43\6\0\7\43\1\0\77\43\1\0"+
+    "\1\43\1\0\4\43\2\0\7\43\1\0\1\43\1\0\4\43\2\0"+
+    "\47\43\1\0\1\43\1\0\4\43\2\0\37\43\1\0\1\43\1\0"+
+    "\4\43\2\0\7\43\1\0\1\43\1\0\4\43\2\0\7\43\1\0"+
+    "\7\43\1\0\27\43\1\0\37\43\1\0\1\43\1\0\4\43\2\0"+
+    "\7\43\1\0\47\43\1\0\23\43\16\0\11\44\56\0\125\43\14\0"+
+    "\u026c\43\2\0\10\43\12\0\32\43\5\0\113\43\25\0\15\43\1\0"+
+    "\4\43\16\0\22\43\16\0\22\43\16\0\15\43\1\0\3\43\17\0"+
+    "\64\43\43\0\1\43\4\0\1\43\3\0\12\44\46\0\12\44\6\0"+
+    "\130\43\10\0\51\43\127\0\35\43\51\0\12\44\36\43\2\0\5\43"+
+    "\u038b\0\154\43\224\0\234\43\4\0\132\43\6\0\26\43\2\0\6\43"+
+    "\2\0\46\43\2\0\6\43\2\0\10\43\1\0\1\43\1\0\1\43"+
+    "\1\0\1\43\1\0\37\43\2\0\65\43\1\0\7\43\1\0\1\43"+
+    "\3\0\3\43\1\0\7\43\3\0\4\43\2\0\6\43\4\0\15\43"+
+    "\5\0\3\43\1\0\7\43\164\0\1\43\15\0\1\43\202\0\1\43"+
+    "\4\0\1\43\2\0\12\43\1\0\1\43\3\0\5\43\6\0\1\43"+
+    "\1\0\1\43\1\0\1\43\1\0\4\43\1\0\3\43\1\0\7\43"+
+    "\3\0\3\43\5\0\5\43\u0ebb\0\2\43\52\0\5\43\5\0\2\43"+
+    "\4\0\126\43\6\0\3\43\1\0\132\43\1\0\4\43\5\0\50\43"+
+    "\4\0\136\43\21\0\30\43\70\0\20\43\u0200\0\u19b6\43\112\0\u51a6\43"+
+    "\132\0\u048d\43\u0773\0\u2ba4\43\u215c\0\u012e\43\2\0\73\43\225\0\7\43"+
+    "\14\0\5\43\5\0\1\43\1\0\12\43\1\0\15\43\1\0\5\43"+
+    "\1\0\1\43\1\0\2\43\1\0\2\43\1\0\154\43\41\0\u016b\43"+
+    "\22\0\100\43\2\0\66\43\50\0\14\43\164\0\5\43\1\0\207\43"+
+    "\23\0\12\44\7\0\32\43\6\0\32\43\13\0\131\43\3\0\6\43"+
+    "\2\0\6\43\2\0\6\43\2\0\3\43\43\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\5\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+
+    "\1\10\1\3\1\11\1\12\1\13\1\14\1\15\1\16"+
+    "\1\17\1\20\1\21\1\22\1\23\1\3\1\24\1\25"+
+    "\1\26\1\27\1\30\1\31\1\32\1\33\1\3\1\34"+
+    "\1\35\1\1\1\36\1\37\1\2\1\40\1\41\1\42"+
+    "\1\43\1\44\1\45\1\46\1\47\1\50\2\51\1\52"+
+    "\1\53\1\54\1\55\1\56\1\57\1\60\1\61\1\62"+
+    "\1\63\1\0\1\64\1\65\2\55\2\56\1\66\1\67"+
+    "\1\64\1\55\1\70\2\56\1\64\3\56\1\71";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[81];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\57\0\136\0\215\0\274\0\353\0\u011a\0\u0149"+
+    "\0\u0149\0\u0178\0\u0149\0\u0149\0\u01a7\0\u01d6\0\u0149\0\u0149"+
+    "\0\u0149\0\u0149\0\u0149\0\u0149\0\u0149\0\u0149\0\u0149\0\u0149"+
+    "\0\u0149\0\u0205\0\u0149\0\u0234\0\u0149\0\u0263\0\u0149\0\u0149"+
+    "\0\u0149\0\u0149\0\u0292\0\u0149\0\u0149\0\u02c1\0\u02f0\0\u0149"+
+    "\0\u0149\0\u031f\0\u0149\0\u0149\0\u034e\0\u037d\0\u0149\0\u0149"+
+    "\0\u0149\0\u0149\0\u0149\0\u03ac\0\u0149\0\u0149\0\u0149\0\u03db"+
+    "\0\u040a\0\u0149\0\u0149\0\u0149\0\u0149\0\u0149\0\u0439\0\u0468"+
+    "\0\u0149\0\u0497\0\u04c6\0\u04f5\0\u0524\0\u0149\0\u0149\0\u0553"+
+    "\0\u0149\0\u0149\0\u0582\0\u05b1\0\u0149\0\u05e0\0\u060f\0\u0149"+
+    "\0\u0149";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[81];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+  private static final String ZZ_TRANS_PACKED_0 =
+    "\3\10\1\11\1\12\1\13\1\14\1\10\1\15\1\10"+
+    "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25"+
+    "\20\10\1\26\10\10\1\27\1\30\1\31\1\30\12\10"+
+    "\1\32\1\0\43\10\1\33\2\34\4\33\1\35\12\33"+
+    "\17\36\1\34\1\33\1\36\1\34\1\37\11\33\11\40"+
+    "\1\41\1\40\1\0\43\40\6\10\1\14\1\10\1\15"+
+    "\1\42\1\16\1\10\1\20\25\10\1\26\3\10\1\43"+
+    "\10\10\5\44\1\45\14\44\17\46\1\44\1\47\1\46"+
+    "\3\44\1\50\7\44\13\7\1\51\40\7\1\51\2\7"+
+    "\75\0\1\52\51\0\1\53\45\0\1\54\1\55\1\56"+
+    "\4\57\1\54\1\57\1\54\1\57\1\54\6\57\2\60"+
+    "\2\61\2\62\1\63\1\64\1\63\1\65\1\66\1\67"+
+    "\1\66\1\70\1\71\1\55\1\57\1\66\13\54\36\0"+
+    "\1\72\21\0\2\34\36\0\1\34\2\0\1\34\34\0"+
+    "\17\36\2\0\1\36\61\0\1\73\32\0\17\46\2\0"+
+    "\1\46\35\0\17\47\2\0\1\47\62\0\1\74\1\75"+
+    "\1\76\1\77\5\0\2\55\36\0\1\55\17\0\1\100"+
+    "\36\0\1\100\15\0\57\101\1\102\2\103\20\102\2\103"+
+    "\2\102\3\103\2\102\1\103\1\102\1\103\2\102\1\103"+
+    "\15\102\1\104\2\105\20\104\2\105\2\104\3\105\2\104"+
+    "\1\105\1\104\1\105\2\104\1\105\15\104\50\0\1\106"+
+    "\1\107\7\0\1\110\36\0\1\110\15\0\60\111\2\112"+
+    "\20\111\2\112\2\111\3\112\2\111\1\112\1\111\1\112"+
+    "\2\111\1\112\15\111\60\113\2\114\20\113\2\114\2\113"+
+    "\3\114\2\113\1\114\1\113\1\114\2\113\1\114\15\113"+
+    "\2\0\1\115\36\0\1\115\15\0\60\116\2\117\20\116"+
+    "\2\117\2\116\3\117\2\116\1\117\1\116\1\117\2\116"+
+    "\1\117\15\116\60\120\2\121\20\120\2\121\2\120\3\121"+
+    "\2\120\1\121\1\120\1\121\2\120\1\121\15\120";
+
+  private static int [] zzUnpackTrans() {
+    int [] result = new int[1598];
+    int offset = 0;
+    offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackTrans(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+  private static final char[] EMPTY_BUFFER = new char[0];
+  private static final int YYEOF = -1;
+  private static java.io.Reader zzReader = null; // Fake
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\5\0\2\1\2\11\1\1\2\11\1\3\1\1\13\11"+
+    "\1\1\1\11\1\1\1\11\1\1\4\11\1\1\2\11"+
+    "\2\1\2\11\1\1\1\15\1\11\2\1\5\11\1\1"+
+    "\3\11\2\1\5\11\1\0\1\1\1\11\4\1\2\11"+
+    "\1\1\2\11\2\1\1\11\2\1\2\11";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[81];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private CharSequence zzBuffer = "";
+
+  /** this buffer may contains the current text array to be matched when it is cheap to acquire it */
+  private char[] zzBufferArray;
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /**
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+    // This adds support for nested states. I'm no JFlex pro, so maybe this is overkill, but it works quite well.
+    private final LinkedList<Integer> states = new LinkedList();
+
+    // This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax)
+    // as well, but is currently unfinished as it requires to tweak more places than just the lexer. 
+    private boolean xmlSchemaMode;
+
+    _RegExLexer(boolean xmlSchemaMode) {
+      this((java.io.Reader)null);
+      this.xmlSchemaMode = xmlSchemaMode;      
+    }
+
+    private void yypushstate(int state) {
+        states.addFirst(yystate());
+        yybegin(state);
+    }
+    private void yypopstate() {
+        final int state = states.removeFirst();
+        yybegin(state);
+    }
+
+    private void handleOptions() {
+      final String o = yytext().toString();
+      if (o.contains("x")) {
+        commentMode = !o.startsWith("-");
+      }
+    }
+
+    // tracks whether the lexer is in comment mode, i.e. whether whitespace is not significant and whether to ignore
+    // text after '#' till EOL
+    boolean commentMode = false;
+
+
+  _RegExLexer(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  _RegExLexer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1334) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+  public final int getTokenStart(){
+    return zzStartRead;
+  }
+
+  public final int getTokenEnd(){
+    return getTokenStart() + yylength();
+  }
+
+  public void reset(CharSequence buffer, int start, int end,int initialState){
+    zzBuffer = buffer;
+    zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer);
+    zzCurrentPos = zzMarkedPos = zzStartRead = start;
+    zzPushbackPos = 0;
+    zzAtEOF  = false;
+    zzAtBOL = true;
+    zzEndRead = end;
+    yybegin(initialState);
+  }
+
+  // For Demetra compatibility
+  public void reset(CharSequence buffer, int initialState){
+    reset(buffer, 0, buffer.length(), initialState);
+  }
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   *
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+    return true;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final CharSequence yytext() {
+    return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
+  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the
+   * matched text.
+   *
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch.
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+  public final char yycharat(int pos) {
+    return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos);
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of
+   * yypushback(int) and a match-all fallback rule) this method
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new Error(message);
+  }
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+    
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  public IElementType advance() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    CharSequence zzBufferL = zzBuffer;
+    char[] zzBufferArrayL = zzBufferArray;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+    int zzPushbackPosL = zzPushbackPos = -1;
+    boolean zzWasPushback;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+      zzState = zzLexicalState;
+
+      zzWasPushback = false;
+
+      zzForAction: {
+        while (true) {
+
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL.charAt(zzCurrentPosL++);
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            zzPushbackPos = zzPushbackPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            zzPushbackPosL = zzPushbackPos;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL.charAt(zzCurrentPosL++);
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 2) == 2 )
+            zzPushbackPosL = zzCurrentPosL;
+
+          if ( (zzAttributes & 1) == 1 ) {
+            zzWasPushback = (zzAttributes & 4) == 4;
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+      if (zzWasPushback)
+        zzMarkedPos = zzPushbackPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 6: 
+          { return RegExpTT.GROUP_END;
+          }
+        case 58: break;
+        case 33: 
+          { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN;
+          }
+        case 59: break;
+        case 13: 
+          { return RegExpTT.STAR;
+          }
+        case 60: break;
+        case 37: 
+          { return RegExpTT.ESC_CHARACTER;
+          }
+        case 61: break;
+        case 9: 
+          { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER;
+          }
+        case 62: break;
+        case 34: 
+          { return RegExpTT.REDUNDANT_ESCAPE;
+          }
+        case 63: break;
+        case 24: 
+          { return RegExpTT.COMMA;
+          }
+        case 64: break;
+        case 54: 
+          { return RegExpTT.POS_LOOKBEHIND;
+          }
+        case 65: break;
+        case 36: 
+          { return RegExpTT.BAD_OCT_VALUE;
+          }
+        case 66: break;
+        case 18: 
+          { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER;
+          }
+        case 67: break;
+        case 46: 
+          { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
+          }
+        case 68: break;
+        case 55: 
+          { return RegExpTT.NEG_LOOKBEHIND;
+          }
+        case 69: break;
+        case 57: 
+          { return RegExpTT.UNICODE_CHAR;
+          }
+        case 70: break;
+        case 53: 
+          { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL;
+          }
+        case 71: break;
+        case 32: 
+          { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS;
+          }
+        case 72: break;
+        case 11: 
+          { return RegExpTT.DOLLAR;
+          }
+        case 73: break;
+        case 47: 
+          { yypopstate(); return RegExpTT.QUOTE_END;
+          }
+        case 74: break;
+        case 50: 
+          { return RegExpTT.POS_LOOKAHEAD;
+          }
+        case 75: break;
+        case 22: 
+          { yypopstate(); return RegExpTT.RBRACE;
+          }
+        case 76: break;
+        case 3: 
+          { return RegExpTT.CHARACTER;
+          }
+        case 77: break;
+        case 51: 
+          { return RegExpTT.NEG_LOOKAHEAD;
+          }
+        case 78: break;
+        case 38: 
+          { return RegExpTT.ESC_CTRL_CHARACTER;
+          }
+        case 79: break;
+        case 23: 
+          { return RegExpTT.NAME;
+          }
+        case 80: break;
+        case 42: 
+          { return RegExpTT.PROPERTY;
+          }
+        case 81: break;
+        case 48: 
+          { return RegExpTT.ANDAND;
+          }
+        case 82: break;
+        case 12: 
+          { return RegExpTT.QUEST;
+          }
+        case 83: break;
+        case 40: 
+          { return RegExpTT.CHAR_CLASS;
+          }
+        case 84: break;
+        case 16: 
+          { return RegExpTT.MINUS;
+          }
+        case 85: break;
+        case 35: 
+          { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
+          }
+        case 86: break;
+        case 15: 
+          { return RegExpTT.UNION;
+          }
+        case 87: break;
+        case 41: 
+          { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
+          }
+        case 88: break;
+        case 52: 
+          { return RegExpTT.OCT_CHAR;
+          }
+        case 89: break;
+        case 4: 
+          { return RegExpTT.DOT;
+          }
+        case 90: break;
+        case 29: 
+          { yybegin(YYINITIAL); return RegExpTT.GROUP_END;
+          }
+        case 91: break;
+        case 21: 
+          { return RegExpTT.NUMBER;
+          }
+        case 92: break;
+        case 19: 
+          { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
+          }
+        case 93: break;
+        case 30: 
+          { handleOptions(); return RegExpTT.OPTIONS_OFF;
+          }
+        case 94: break;
+        case 31: 
+          { yybegin(YYINITIAL); return RegExpTT.COLON;
+          }
+        case 95: break;
+        case 25: 
+          { assert false : yytext();
+          }
+        case 96: break;
+        case 27: 
+          { yypopstate(); return RegExpTT.CLASS_END;
+          }
+        case 97: break;
+        case 10: 
+          { return RegExpTT.CARET;
+          }
+        case 98: break;
+        case 1: 
+          { handleOptions(); return RegExpTT.OPTIONS_ON;
+          }
+        case 99: break;
+        case 39: 
+          { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
+          }
+        case 100: break;
+        case 17: 
+          { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER;
+          }
+        case 101: break;
+        case 56: 
+          { return RegExpTT.HEX_CHAR;
+          }
+        case 102: break;
+        case 20: 
+          { return RegExpTT.BAD_CHARACTER;
+          }
+        case 103: break;
+        case 5: 
+          { return RegExpTT.GROUP_BEGIN;
+          }
+        case 104: break;
+        case 8: 
+          { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN;
+          }
+        case 105: break;
+        case 49: 
+          { return RegExpTT.NON_CAPT_GROUP;
+          }
+        case 106: break;
+        case 7: 
+          { yypushstate(EMBRACED); return RegExpTT.LBRACE;
+          }
+        case 107: break;
+        case 43: 
+          { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
+          }
+        case 108: break;
+        case 45: 
+          { return RegExpTT.BAD_HEX_VALUE;
+          }
+        case 109: break;
+        case 2: 
+          { yypopstate(); return RegExpTT.COMMENT;
+          }
+        case 110: break;
+        case 44: 
+          { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
+          }
+        case 111: break;
+        case 26: 
+          { yybegin(CLASS2); return RegExpTT.CHARACTER;
+          }
+        case 112: break;
+        case 14: 
+          { return RegExpTT.PLUS;
+          }
+        case 113: break;
+        case 28: 
+          { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
+          }
+        case 114: break;
+        default:
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+            return null;
+          }
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpAtom.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpAtom.java
new file mode 100644 (file)
index 0000000..13765f9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+/**
+ * Represents elements that can be part of a {@link org.intellij.lang.regexp.psi.RegExpBranch}.
+ */
+public interface RegExpAtom extends RegExpElement {
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBackref.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBackref.java
new file mode 100644 (file)
index 0000000..ebf5fd8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.Nullable;
+
+public interface RegExpBackref extends RegExpAtom {
+    /**
+     * Returns the group-index the backref refers to
+     */
+    int getIndex();
+
+    /**
+     * The referenced group, or null if no such group exists
+     */
+    @Nullable
+    RegExpGroup resolve();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBoundary.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBoundary.java
new file mode 100644 (file)
index 0000000..a2244ac
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface RegExpBoundary extends RegExpAtom {
+    /**
+     * Boundary type enumeration.
+     */
+    enum Type  {
+        LINE_START, LINE_END,
+        WORD, NON_WORD,
+        BEGIN, END, END_NO_LINE_TERM,
+        PREVIOUS_MATCH
+    }
+
+    @NotNull
+    Type getType();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBranch.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpBranch.java
new file mode 100644 (file)
index 0000000..10e51b6
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A branch represents an alternative in a regex pattern: abc | xyz
+ */
+public interface RegExpBranch extends RegExpElement {
+    /**
+     * Returns the atoms making up the branch.
+     * @see org.intellij.lang.regexp.psi.RegExpAtom 
+     */
+    @NotNull
+    RegExpAtom[] getAtoms();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpChar.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpChar.java
new file mode 100644 (file)
index 0000000..72bdd2c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents a simple or escaped character
+ */
+public interface RegExpChar extends RegExpAtom, RegExpClassElement, RegExpCharRange.Endpoint {
+    /**
+     * Character type enumeration. Represents either a plain character ("a"),
+     * a hex encoded character value ("\x61"),
+     * an octal encoded character value ("\0141"), or
+     * a unicode escape character ("\u0061")
+     */
+    enum Type {
+        CHAR, HEX, OCT, UNICODE
+    }
+
+    /**
+     * Returns the type of this character.
+     * @see org.intellij.lang.regexp.psi.RegExpChar.Type
+     */
+    @NotNull
+    Type getType();
+
+    /**
+     * Returns possibly unescaped character-value.
+     * Null if escape sequence is invalid.
+     */
+    @Nullable
+    Character getValue();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpCharRange.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpCharRange.java
new file mode 100644 (file)
index 0000000..437cfc3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a character range as in [a-z]. 
+ */
+public interface RegExpCharRange extends RegExpElement, RegExpClassElement {
+    interface Endpoint extends RegExpClassElement { }
+
+    @NotNull
+    Endpoint getFrom();
+
+    @NotNull
+    Endpoint getTo();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClass.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClass.java
new file mode 100644 (file)
index 0000000..897c3d4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a class indicated by [...]
+ */
+public interface RegExpClass extends RegExpAtom {
+    /**
+     * True, is the class is negated: [^...]
+     */
+    boolean isNegated();
+
+    @NotNull
+    RegExpClassElement[] getElements();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClassElement.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClassElement.java
new file mode 100644 (file)
index 0000000..933243e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+/**
+ * Base interface for elements that can occur inside character classes ([...])
+ */
+public interface RegExpClassElement extends RegExpElement {
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClosure.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpClosure.java
new file mode 100644 (file)
index 0000000..ffcc930
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents an atom with a quantifier, such as ?, *, + or {min,max}
+ */
+public interface RegExpClosure extends RegExpAtom {
+    @NotNull
+    RegExpQuantifier getQuantifier();
+
+    @NotNull
+    RegExpAtom getAtom();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElement.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElement.java
new file mode 100644 (file)
index 0000000..9b3cd51
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.lang.ASTNode;
+import org.jetbrains.annotations.NotNull;
+
+public interface RegExpElement extends PsiElement {
+    @NotNull
+    ASTNode getNode();
+
+    String getUnescapedText();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElementVisitor.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpElementVisitor.java
new file mode 100644 (file)
index 0000000..ab027bd
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import com.intellij.psi.PsiElementVisitor;
+import org.intellij.lang.regexp.psi.impl.RegExpOptionsImpl;
+
+public class RegExpElementVisitor extends PsiElementVisitor {
+
+    public void visitRegExpElement(RegExpElement element) {
+    }
+
+    public void visitRegExpChar(RegExpChar ch) {
+        visitRegExpElement(ch);
+    }
+
+    public void visitRegExpCharRange(RegExpCharRange range) {
+        visitRegExpElement(range);
+    }
+
+    public void visitSimpleClass(RegExpSimpleClass simpleClass) {
+        visitRegExpElement(simpleClass);
+    }
+
+    public void visitRegExpClass(RegExpClass expClass) {
+        visitRegExpElement(expClass);
+    }
+
+    public void visitRegExpGroup(RegExpGroup group) {
+        visitRegExpElement(group);
+    }
+
+    public void visitRegExpOptions(RegExpOptionsImpl options) {
+        visitRegExpElement(options);
+    }
+
+    public void visitRegExpProperty(RegExpProperty property) {
+        visitRegExpElement(property);
+    }
+
+    public void visitRegExpBranch(RegExpBranch branch) {
+        visitRegExpElement(branch);
+    }
+
+    public void visitRegExpPattern(RegExpPattern pattern) {
+        visitRegExpElement(pattern);
+    }
+
+    public void visitRegExpBackref(RegExpBackref backref) {
+        visitRegExpElement(backref);
+    }
+
+    public void visitRegExpClosure(RegExpClosure closure) {
+        visitRegExpElement(closure);
+    }
+
+    public void visitRegExpQuantifier(RegExpQuantifier quantifier) {
+        visitRegExpElement(quantifier);
+    }
+
+    public void visitRegExpBoundary(RegExpBoundary boundary) {
+        visitRegExpElement(boundary);
+    }
+
+    public void visitRegExpSetOptions(RegExpSetOptions options) {
+        visitRegExpElement(options);
+    }
+
+    public void visitRegExpIntersection(RegExpIntersection intersection) {
+        visitRegExpElement(intersection);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpGroup.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpGroup.java
new file mode 100644 (file)
index 0000000..7770f6a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.Nullable;
+
+public interface RegExpGroup extends RegExpAtom {
+    boolean isCapturing();
+
+    @Nullable
+    RegExpPattern getPattern();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpIntersection.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpIntersection.java
new file mode 100644 (file)
index 0000000..a32eae0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents an intersection of class elements: [a-z&&[^cd]]
+ */
+public interface RegExpIntersection extends RegExpClassElement {
+    @NotNull
+    RegExpClassElement getLOperand();
+
+    @Nullable
+    RegExpClassElement getROperand();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpOptions.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpOptions.java
new file mode 100644 (file)
index 0000000..dc927f1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+/**
+ * Represents an inline options element (?x) or (?-x). Returned from {@link org.intellij.lang.regexp.psi.RegExpSetOptions}
+ */
+public interface RegExpOptions extends RegExpElement {
+    /**
+     * Checks whether a certain option is set.
+     */
+    boolean isSet(char option);
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpPattern.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpPattern.java
new file mode 100644 (file)
index 0000000..180ed5d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Basic element that holds a whole pattern that consists of one or more branches.
+ */
+public interface RegExpPattern extends RegExpElement {
+    @NotNull
+    RegExpBranch[] getBranches();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpProperty.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpProperty.java
new file mode 100644 (file)
index 0000000..7dbd2a8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import com.intellij.lang.ASTNode;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents a character property as in \p{Digit}
+ */
+public interface RegExpProperty extends RegExpAtom, RegExpClassElement {
+    /**
+     * True, if \P, false if \p
+     */
+    boolean isNegated();
+
+    /**
+     * The node the represents the category name, e.g. "Digit"
+     */
+    @Nullable
+    ASTNode getCategoryNode();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpQuantifier.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpQuantifier.java
new file mode 100644 (file)
index 0000000..c182246
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface RegExpQuantifier extends RegExpAtom {
+
+    @NotNull
+    RegExpAtom getAtom();
+
+    /**
+     * The min,max occurrence count the quantifier represents. This is either an instance of
+     * {@link org.intellij.lang.regexp.psi.RegExpQuantifier.SimpleCount} for the ?, * or +
+     * quantifiers, or an arbitrary instance of the {@link org.intellij.lang.regexp.psi.RegExpQuantifier.Count}
+     * interface that returns the values obtained from the {min,max} quantifier.
+     */
+    @NotNull
+    Count getCount();
+
+    /**
+     * The "greedyness" type of the quantifier.  
+     */
+    @NotNull
+    Type getType();
+
+    interface Count {
+        int getMin();
+        int getMax();
+    }
+
+    enum SimpleCount implements Count {
+        /** ? */
+        ONE_OR_ZERO(0, 1),
+        /** * */
+        ZERO_OR_MORE(0, Integer.MAX_VALUE),
+        /** + */
+        ONE_OR_MORE(1, Integer.MAX_VALUE),;
+
+        private final int myMin;
+        private final int myMax;
+
+        SimpleCount(int min, int max) {
+            myMin = min;
+            myMax = max;
+        }
+
+        public int getMin() {
+            return myMin;
+        }
+        public int getMax() {
+            return myMax;
+        }
+    }
+
+    enum Type {
+        GREEDY(""),
+        /** ? */
+        RELUCTANT("?"),
+        /** + */
+        POSSESSIVE("+");
+
+        private final String myToken;
+        Type(String ch) {
+            myToken = ch;
+        }
+        public String getToken() {
+            return myToken;
+        }
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpRecursiveElementVisitor.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpRecursiveElementVisitor.java
new file mode 100644 (file)
index 0000000..7557af7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+public class RegExpRecursiveElementVisitor extends RegExpElementVisitor {
+    public void visitRegExpElement(RegExpElement element) {
+        element.acceptChildren(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSetOptions.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSetOptions.java
new file mode 100644 (file)
index 0000000..77249a1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.Nullable;
+
+public interface RegExpSetOptions extends RegExpAtom {
+    @Nullable
+    RegExpOptions getOnOptions();
+
+    @Nullable
+    RegExpOptions getOffOptions();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSimpleClass.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/RegExpSimpleClass.java
new file mode 100644 (file)
index 0000000..e983e74
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a simple character class.
+ */
+public interface RegExpSimpleClass extends RegExpAtom, RegExpClassElement, RegExpCharRange.Endpoint {
+    enum Kind {
+        /** . */  ANY,
+        /** \d */ DIGIT, /** \D */ NON_DIGIT,
+        /** \w */ WORD,  /** \W */ NON_WORD,
+        /** \s */ SPACE, /** \S */ NON_SPACE
+    }
+
+    @NotNull
+    Kind getKind();
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBackrefImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBackrefImpl.java
new file mode 100644 (file)
index 0000000..4819ea3
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiElementFilter;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ArrayUtil;
+
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpElement;
+import org.intellij.lang.regexp.psi.RegExpGroup;
+import org.intellij.lang.regexp.psi.RegExpBackref;
+
+public class RegExpBackrefImpl extends RegExpElementImpl implements RegExpBackref {
+    public RegExpBackrefImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public int getIndex() {
+        final String s = getUnescapedText();
+        assert s.charAt(0) == '\\';
+        return Integer.parseInt(s.substring(1));
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpBackref(this);
+    }
+
+    public RegExpGroup resolve() {
+        final int index = getIndex();
+
+        final PsiElementProcessor.FindFilteredElement<RegExpElement> processor = new PsiElementProcessor.FindFilteredElement<RegExpElement>(new PsiElementFilter() {
+            int groupCount;
+
+            public boolean isAccepted(PsiElement element) {
+                if (element instanceof RegExpGroup) {
+                    if (((RegExpGroup)element).isCapturing() && ++groupCount == index) {
+                        return true;
+                    }
+                }
+                return element == RegExpBackrefImpl.this;
+            }
+        });
+
+        PsiTreeUtil.processElements(getContainingFile(), processor);
+        if (processor.getFoundElement() instanceof RegExpGroup) {
+            return (RegExpGroup)processor.getFoundElement();
+        }
+        return null;
+    }
+
+    public PsiReference getReference() {
+        return new PsiReference() {
+            public PsiElement getElement() {
+                return RegExpBackrefImpl.this;
+            }
+
+            public TextRange getRangeInElement() {
+                return TextRange.from(0, getElement().getTextLength());
+            }
+
+            public String getCanonicalText() {
+                return getElement().getText();
+            }
+
+            public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+                throw new IncorrectOperationException();
+            }
+
+            public PsiElement bindToElement(PsiElement element) throws IncorrectOperationException {
+                throw new IncorrectOperationException();
+            }
+
+            public boolean isReferenceTo(PsiElement element) {
+                return Comparing.equal(element, resolve());
+            }
+
+            public boolean isSoft() {
+                return false;
+            }
+
+            public PsiElement resolve() {
+                return RegExpBackrefImpl.this.resolve();
+            }
+            
+            public Object[] getVariants() {
+                return ArrayUtil.EMPTY_OBJECT_ARRAY;
+            }
+        };
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBoundaryImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBoundaryImpl.java
new file mode 100644 (file)
index 0000000..8ec6cc2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.IElementType;
+
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpBoundary;
+import org.intellij.lang.regexp.RegExpTT;
+
+public class RegExpBoundaryImpl extends RegExpElementImpl implements RegExpBoundary {
+    public RegExpBoundaryImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    @NotNull
+    public Type getType() {
+        final IElementType type = getNode().getElementType();
+        if (type == RegExpTT.CARET) {
+            return Type.LINE_START;
+        } else if (type == RegExpTT.DOLLAR) {
+            return Type.LINE_END;
+        } else {
+            assert type == RegExpTT.BOUNDARY;
+            final String s = getUnescapedText();
+            if (s.equals("\\b")) {
+                return Type.WORD;
+            } else if (s.equals("\\B))")) {
+                return Type.NON_WORD;
+            } else if (s.equals("\\A))")) {
+                return Type.BEGIN;
+            } else if (s.equals("\\Z))")) {
+                return Type.END_NO_LINE_TERM;
+            } else if (s.equals("\\z))")) {
+                return Type.END;
+            } else if (s.equals("\\G))")) {
+                return Type.PREVIOUS_MATCH;
+            }
+        }
+        assert false;
+        return null;
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpBoundary(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBranchImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpBranchImpl.java
new file mode 100644 (file)
index 0000000..8e8867f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpBranch;
+
+public class RegExpBranchImpl extends RegExpElementImpl implements RegExpBranch {
+    public RegExpBranchImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    @NotNull
+    public RegExpAtom[] getAtoms() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpElementTypes.ATOMS);
+        final RegExpAtom[] atoms = new RegExpAtom[nodes.length];
+        for (int i = 0; i < atoms.length; i++) {
+            atoms[i] = (RegExpAtom)nodes[i].getPsi();
+        }
+        return atoms;
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpBranch(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharImpl.java
new file mode 100644 (file)
index 0000000..2be376b
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.StringEscapesTokenTypes;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.psi.RegExpChar;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+
+public class RegExpCharImpl extends RegExpElementImpl implements RegExpChar {
+    private static final TokenSet OCT_CHARS = TokenSet.create(RegExpTT.OCT_CHAR, RegExpTT.BAD_OCT_VALUE);
+    private static final TokenSet HEX_CHARS = TokenSet.create(RegExpTT.HEX_CHAR, RegExpTT.BAD_HEX_VALUE);
+    private static final TokenSet UNICODE_CHARS = TokenSet.create(RegExpTT.HEX_CHAR, StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN);
+
+    public RegExpCharImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    @NotNull
+    public Type getType() {
+        final ASTNode child = getNode().getFirstChildNode();
+        assert child != null;
+        final IElementType t = child.getElementType();
+        if (OCT_CHARS.contains(t)) {
+            return Type.OCT;
+        } else if (HEX_CHARS.contains(t)) {
+            return Type.HEX;
+        } else if (UNICODE_CHARS.contains(t)) {
+            return Type.UNICODE;
+        } else {
+            return Type.CHAR;
+        }
+    }
+
+    @Nullable
+    public Character getValue() {
+        return unescapeChar(getUnescapedText());
+    }
+
+    @Nullable
+    static Character unescapeChar(String s) {
+        assert s.length() > 0;
+
+        boolean escaped = false;
+        for (int idx = 0; idx < s.length(); idx++) {
+            char ch = s.charAt(idx);
+            if (!escaped) {
+                if (ch == '\\') {
+                    escaped = true;
+                } else {
+                    return ch;
+                }
+            } else {
+                switch (ch) {
+                    case'n':
+                        return '\n';
+                    case'r':
+                        return '\r';
+                    case't':
+                        return '\t';
+                    case'f':
+                        return '\f';
+                    case'c':
+                        return (char)(ch ^ 64);
+                    case'x':
+                        return parseNumber(idx, s, 16, 2, true);
+                    case'u':
+                        return parseNumber(idx, s, 16, 4, true);
+                    case'0':
+                        return parseNumber(idx, s, 8, 3, false);
+                    default:
+                        if (Character.isLetter(ch)) {
+                            return null;
+                        }
+                        return ch;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    static Character parseNumber(int idx, String s, int radix, int len, boolean strict) {
+        final int start = idx + 1;
+        final int end = start + len;
+        try {
+            int sum = 0;
+            int i;
+            for (i = start; i < end && i < s.length(); i++) {
+                sum *= radix;
+                sum += Integer.valueOf(s.substring(i, i + 1), radix);
+            }
+            if (i-start == 0) return null;
+            return i-start < len && strict ? null : (char)sum;
+        } catch (NumberFormatException e1) {
+            return null;
+        }
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpChar(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharRangeImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpCharRangeImpl.java
new file mode 100644 (file)
index 0000000..426fb57
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.psi.RegExpCharRange;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+
+public class RegExpCharRangeImpl extends RegExpElementImpl implements RegExpCharRange {
+    private static final TokenSet E = TokenSet.create(RegExpElementTypes.CHAR, RegExpElementTypes.SIMPLE_CLASS);
+
+    public RegExpCharRangeImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    @NotNull
+    public Endpoint getFrom() {
+        return (Endpoint)getCharNode(0);
+    }
+    @NotNull
+    public Endpoint getTo() {
+        return (Endpoint)getCharNode(1);
+    }
+
+    private PsiElement getCharNode(int idx) {
+        final ASTNode[] ch = getNode().getChildren(E);
+        assert ch.length == 2;
+        return ch[idx].getPsi();
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpCharRange(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClassImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClassImpl.java
new file mode 100644 (file)
index 0000000..669da55
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.psi.RegExpClass;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpClassElement;
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.RegExpElementTypes;
+
+public class RegExpClassImpl extends RegExpElementImpl implements RegExpClass {
+
+    public RegExpClassImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public boolean isNegated() {
+        final ASTNode node = getNode().getFirstChildNode();
+        return node != null && node.getElementType() == RegExpTT.CARET;
+    }
+
+    @NotNull
+    public RegExpClassElement[] getElements() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpElementTypes.CLASS_ELEMENTS);
+        RegExpClassElement[] e = new RegExpClassElement[nodes.length];
+        for (int i = 0; i < e.length; i++) {
+            e[i] = (RegExpClassElement)nodes[i].getPsi();
+        }
+        return e;
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpClass(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClosureImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpClosureImpl.java
new file mode 100644 (file)
index 0000000..0d06f6c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.util.PsiTreeUtil;
+
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpQuantifier;
+import org.intellij.lang.regexp.psi.RegExpClosure;
+
+public class RegExpClosureImpl extends RegExpElementImpl implements RegExpClosure {
+
+    public RegExpClosureImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpClosure(this);
+    }
+
+    @NotNull
+    public RegExpQuantifier getQuantifier() {
+        final ASTNode node = getNode().findChildByType(RegExpElementTypes.QUANTIFIER);
+        assert node != null;
+        return (RegExpQuantifier)node.getPsi();
+    }
+
+    @NotNull
+    public RegExpAtom getAtom() {
+        final RegExpAtom atom = PsiTreeUtil.getChildOfType(this, RegExpAtom.class);
+        assert atom != null;
+        return atom;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java
new file mode 100644 (file)
index 0000000..dd48dac
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiLiteralExpression;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.intellij.lang.regexp.RegExpLanguage;
+import org.intellij.lang.regexp.psi.RegExpElement;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class RegExpElementImpl extends ASTWrapperPsiElement implements RegExpElement {
+    public RegExpElementImpl(ASTNode node) {
+        super(node);
+    }
+
+    @NotNull
+    public Language getLanguage() {
+        return RegExpLanguage.INSTANCE;
+    }
+
+    @NotNull
+    @SuppressWarnings({ "ConstantConditions", "EmptyMethod" })
+    public ASTNode getNode() {
+        return super.getNode();
+    }
+
+    public String toString() {
+        return getClass().getSimpleName() + ": <" + getUnescapedText() + ">";
+    }
+
+    public void accept(@NotNull PsiElementVisitor visitor) {
+        if (visitor instanceof RegExpElementVisitor) {
+            accept((RegExpElementVisitor)visitor);
+        } else {
+            super.accept(visitor);
+        }
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpElement(this);
+    }
+
+    public PsiElement replace(@NotNull PsiElement psiElement) throws IncorrectOperationException {
+        final ASTNode node = psiElement.getNode();
+        assert node != null;
+        getNode().getTreeParent().replaceChild(getNode(), node);
+        return psiElement;
+    }
+
+    public void delete() throws IncorrectOperationException {
+        getNode().getTreeParent().removeChild(getNode());
+    }
+
+    public final String getUnescapedText() {
+        if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(this)) {
+            // do not attempt to decode text if PsiElement is part of prefix/suffix
+            return getText();
+        }
+        if (isInsideStringLiteral()) {
+            return StringUtil.unescapeStringCharacters(getNode().getText());
+        } else {
+            return getNode().getText();
+        }
+    }
+
+    protected final boolean isInsideStringLiteral() {
+        return getContainingFile().getContext() instanceof PsiLiteralExpression;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpGroupImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpGroupImpl.java
new file mode 100644 (file)
index 0000000..9b8fa67
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpGroup;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+
+public class RegExpGroupImpl extends RegExpElementImpl implements RegExpGroup {
+    public RegExpGroupImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpGroup(this);
+    }
+
+    public boolean isCapturing() {
+        final ASTNode node = getNode().getFirstChildNode();
+        return node != null && node.getElementType() == RegExpTT.GROUP_BEGIN;
+    }
+
+    public RegExpPattern getPattern() {
+        final ASTNode node = getNode().findChildByType(RegExpElementTypes.PATTERN);
+        return node != null ? (RegExpPattern)node.getPsi() : null;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpIntersectionImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpIntersectionImpl.java
new file mode 100644 (file)
index 0000000..ff0b7b0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import org.intellij.lang.regexp.psi.RegExpClassElement;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpIntersection;
+import org.intellij.lang.regexp.RegExpElementTypes;
+
+public class RegExpIntersectionImpl extends RegExpElementImpl implements RegExpIntersection {
+    public RegExpIntersectionImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpIntersection(this);
+    }
+
+    @NotNull
+    public RegExpClassElement getLOperand() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpElementTypes.CLASS_ELEMENTS);
+        return (RegExpClassElement)nodes[0].getPsi();
+    }
+
+    @Nullable
+    public RegExpClassElement getROperand() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpElementTypes.CLASS_ELEMENTS);
+        return nodes.length > 1 ? (RegExpClassElement)nodes[1].getPsi() : null;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpOptionsImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpOptionsImpl.java
new file mode 100644 (file)
index 0000000..46022bf
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpOptions;
+
+public class RegExpOptionsImpl extends RegExpElementImpl implements RegExpOptions {
+    public RegExpOptionsImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpOptions(this);
+    }
+
+    public boolean isSet(char option) {
+        return getUnescapedText().indexOf(option) != -1;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPatternImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPatternImpl.java
new file mode 100644 (file)
index 0000000..61dce96
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.TokenSet;
+
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+import org.intellij.lang.regexp.psi.RegExpBranch;
+
+public class RegExpPatternImpl extends RegExpElementImpl implements RegExpPattern {
+    private static final TokenSet BRANCH = TokenSet.create(RegExpElementTypes.BRANCH);
+
+    public RegExpPatternImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpPattern(this);
+    }
+
+    @NotNull
+    public RegExpBranch[] getBranches() {
+        final ASTNode[] nodes = getNode().getChildren(BRANCH);
+        final RegExpBranch[] branches = new RegExpBranch[nodes.length];
+        for (int i = 0; i < branches.length; i++) {
+            branches[i] = (RegExpBranch)nodes[i].getPsi();
+        }
+        return branches;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPropertyImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpPropertyImpl.java
new file mode 100644 (file)
index 0000000..2bc1133
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.codeInsight.lookup.LookupValueFactory;
+import com.intellij.codeInsight.lookup.LookupValueWithPriority;
+import com.intellij.codeInsight.lookup.LookupValueWithUIHint;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.util.Icons;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
+
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpProperty;
+
+import java.awt.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RegExpPropertyImpl extends RegExpElementImpl implements RegExpProperty {
+    public RegExpPropertyImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public PsiReference getReference() {
+        final ASTNode lbrace = getNode().findChildByType(RegExpTT.LBRACE);
+        if (lbrace == null) return null;
+        return new MyPsiReference();
+    }
+
+    public boolean isNegated() {
+        final ASTNode node = getNode().findChildByType(RegExpTT.PROPERTY);
+        return node != null && node.textContains('P');
+    }
+
+    @Nullable
+    public ASTNode getCategoryNode() {
+        return getNode().findChildByType(RegExpTT.NAME);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpProperty(this);
+    }
+
+    public static boolean isValidCategory(String category) {
+        if (category.startsWith("In")) {
+            try {
+                return Character.UnicodeBlock.forName(category.substring(2)) != null;
+            } catch (IllegalArgumentException e) {
+                return false;
+            }
+        }
+        if (category.startsWith("Is")) {
+            category = category.substring(2);
+        }
+        for (String[] name : PROPERTY_NAMES) {
+            if (name[0].equals(category)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private class MyPsiReference implements PsiReference {
+        public PsiElement getElement() {
+            return RegExpPropertyImpl.this;
+        }
+
+        public TextRange getRangeInElement() {
+            final ASTNode lbrace = getNode().findChildByType(RegExpTT.LBRACE);
+            assert lbrace != null;
+            final ASTNode rbrace = getNode().findChildByType(RegExpTT.RBRACE);
+            int to = rbrace == null ? getTextRange().getEndOffset() : rbrace.getTextRange().getEndOffset() - 1;
+
+            final TextRange t = new TextRange(lbrace.getStartOffset() + 1, to);
+            return t.shiftRight(-getTextRange().getStartOffset());
+        }
+
+        @Nullable
+        public PsiElement resolve() {
+            return RegExpPropertyImpl.this;
+        }
+
+        public String getCanonicalText() {
+            return getRangeInElement().substring(getElement().getText());
+        }
+
+        public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+            throw new IncorrectOperationException();
+        }
+
+        public PsiElement bindToElement(PsiElement element) throws IncorrectOperationException {
+            throw new IncorrectOperationException();
+        }
+
+        public boolean isReferenceTo(PsiElement element) {
+            return false;
+        }
+
+        public Object[] getVariants() {
+            final ASTNode categoryNode = getCategoryNode();
+            if (categoryNode != null && categoryNode.getText().startsWith("In") && !categoryNode.getText().startsWith("Intelli")) {
+                return UNICODE_BLOCKS;
+            } else {
+                final Object[] objects = new Object[PROPERTY_NAMES.length];
+                for (int i = 0; i < objects.length; i++) {
+                    final String[] prop = PROPERTY_NAMES[i];
+                    objects[i] = new MyLookupValue(prop);
+
+                }
+                return objects;
+            }
+        }
+
+        public boolean isSoft() {
+            return true;
+        }
+
+        private class MyLookupValue extends LookupValueFactory.LookupValueWithIcon implements LookupValueWithPriority, LookupValueWithUIHint {
+            private final String[] myProp;
+
+            public MyLookupValue(String[] prop) {
+                super(prop[0], Icons.PROPERTY_ICON);
+                myProp = prop;
+            }
+
+            public String getPresentation() {
+                final ASTNode categoryNode = getCategoryNode();
+                if (categoryNode != null) {
+                    if (categoryNode.getText().startsWith("Is")) {
+                        return "Is" + super.getPresentation();
+                    }
+                }
+                return super.getPresentation();
+            }
+
+            public int getPriority() {
+                final String name = myProp[0];
+                if (name.equals("all")) return HIGH + 1;
+                if (name.startsWith("java")) return HIGHER;
+                return name.length() > 2 ? HIGH : NORMAL;
+            }
+
+            public String getTypeHint() {
+                return myProp.length > 1 ? myProp[1] : ("Character.is" + myProp[0].substring("java".length()) + "()");
+            }
+
+            @Nullable
+            public Color getColorHint() {
+                return null;
+            }
+
+            public boolean isBold() {
+                return false;
+            }
+        }
+    }
+
+
+    private static final String[] UNICODE_BLOCKS;
+    static {
+        final Field[] fields = Character.UnicodeBlock.class.getFields();
+        final List<String> unicodeBlocks = new ArrayList<String>(fields.length);
+        for (Field field : fields) {
+            if (field.getType().equals(Character.UnicodeBlock.class)) {
+                if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
+                    unicodeBlocks.add("In" + field.getName());
+                }
+            }
+        }
+        UNICODE_BLOCKS = unicodeBlocks.toArray(new String[unicodeBlocks.size()]);
+    }
+    public static final String[][] PROPERTY_NAMES = {
+            { "Cn", "UNASSIGNED" },
+            { "Lu", "UPPERCASE_LETTER" },
+            { "Ll", "LOWERCASE_LETTER" },
+            { "Lt", "TITLECASE_LETTER" },
+            { "Lm", "MODIFIER_LETTER" },
+            { "Lo", "OTHER_LETTER" },
+            { "Mn", "NON_SPACING_MARK" },
+            { "Me", "ENCLOSING_MARK" },
+            { "Mc", "COMBINING_SPACING_MARK" },
+            { "Nd", "DECIMAL_DIGIT_NUMBER" },
+            { "Nl", "LETTER_NUMBER" },
+            { "No", "OTHER_NUMBER" },
+            { "Zs", "SPACE_SEPARATOR" },
+            { "Zl", "LINE_SEPARATOR" },
+            { "Zp", "PARAGRAPH_SEPARATOR" },
+            { "Cc", "CNTRL" },
+            { "Cf", "FORMAT" },
+            { "Co", "PRIVATE USE" },
+            { "Cs", "SURROGATE" },
+            { "Pd", "DASH_PUNCTUATION" },
+            { "Ps", "START_PUNCTUATION" },
+            { "Pe", "END_PUNCTUATION" },
+            { "Pc", "CONNECTOR_PUNCTUATION" },
+            { "Po", "OTHER_PUNCTUATION" },
+            { "Sm", "MATH_SYMBOL" },
+            { "Sc", "CURRENCY_SYMBOL" },
+            { "Sk", "MODIFIER_SYMBOL" },
+            { "So", "OTHER_SYMBOL" },
+            { "L", "LETTER" },
+            { "M", "MARK" },
+            { "N", "NUMBER" },
+            { "Z", "SEPARATOR" },
+            { "C", "CONTROL" },
+            { "P", "PUNCTUATION" },
+            { "S", "SYMBOL" },
+            { "LD", "LETTER_OR_DIGIT" },
+            { "L1", "Latin-1" },
+            { "all", "ALL" },
+            { "ASCII", "ASCII" },
+            { "Alnum", "Alphanumeric characters" },
+            { "Alpha", "Alphabetic characters" },
+            { "Blank", "Space and tab characters" },
+            { "Cntrl", "Control characters" },
+            { "Digit", "Numeric characters" },
+            { "Graph", "printable and visible" },
+            { "Lower", "Lower-case alphabetic" },
+            { "Print", "Printable characters" },
+            { "Punct", "Punctuation characters" },
+            { "Space", "Space characters" },
+            { "Upper", "Upper-case alphabetic" },
+            { "XDigit", "hexadecimal digits" },
+            { "javaLowerCase", },
+            { "javaUpperCase", },
+            { "javaTitleCase", },
+            { "javaDigit", },
+            { "javaDefined", },
+            { "javaLetter", },
+            { "javaLetterOrDigit", },
+            { "javaJavaIdentifierStart", },
+            { "javaJavaIdentifierPart", },
+            { "javaUnicodeIdentifierStart", },
+            { "javaUnicodeIdentifierPart", },
+            { "javaIdentifierIgnorable", },
+            { "javaSpaceChar", },
+            { "javaWhitespace", },
+            { "javaISOControl", },
+            { "javaMirrored", },
+    };
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpQuantifierImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpQuantifierImpl.java
new file mode 100644 (file)
index 0000000..dccb75d
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.RegExpElementTypes;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpQuantifier;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+
+public class RegExpQuantifierImpl extends RegExpElementImpl implements RegExpQuantifier {
+
+    public RegExpQuantifierImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpQuantifier(this);
+    }
+
+    @NotNull
+    public RegExpAtom getAtom() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpElementTypes.ATOMS);
+        assert nodes.length > 0;
+        return (RegExpAtom)nodes[0].getPsi();
+    }
+
+    @NotNull
+    public Count getCount() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpTT.QUANTIFIERS);
+        assert nodes.length > 0;
+
+        final IElementType type = nodes[0].getElementType();
+        if (type == RegExpTT.QUEST) {
+            return SimpleCount.ONE_OR_ZERO;
+        } else if (type == RegExpTT.STAR) {
+            return SimpleCount.ZERO_OR_MORE;
+        } else if (type == RegExpTT.PLUS) {
+            return SimpleCount.ONE_OR_MORE;
+        } else if (type == RegExpTT.LBRACE) {
+            final ASTNode[] numbers = getNode().getChildren(TokenSet.create(RegExpTT.NUMBER));
+            if (numbers.length >= 1) {
+                final int min = Integer.parseInt(numbers[0].getText());
+                final int max;
+                if (numbers.length == 2) {
+                    max = Integer.parseInt(numbers[1].getText());
+                } else if (getNode().findChildByType(RegExpTT.COMMA) != null) {
+                    max = Integer.MAX_VALUE;
+                } else {
+                    max = min;
+                }
+                return new RepeatedCount(min, max);
+            }
+            // syntactically incorrect
+            return new RepeatedCount(-1, -1);
+        }
+
+        assert false;
+        return null;
+    }
+
+    @NotNull
+    public Type getType() {
+        final ASTNode[] nodes = getNode().getChildren(RegExpTT.QUANTIFIERS);
+        if (nodes.length > 1) {
+            final IElementType type = nodes[1].getElementType();
+            if (type == RegExpTT.QUEST) {
+                return Type.RELUCTANT;
+            } else if (type == RegExpTT.PLUS) {
+                return Type.POSSESSIVE;
+            }
+        }
+        return Type.GREEDY;
+    }
+
+    private static class RepeatedCount implements RegExpQuantifier.Count {
+        private final int myMin;
+        private final int myMax;
+
+        public RepeatedCount(int min, int max) {
+            myMin = min;
+            myMax = max;
+        }
+
+        public int getMin() {
+            return myMin;
+        }
+
+        public int getMax() {
+            return myMax;
+        }
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSetOptionsImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSetOptionsImpl.java
new file mode 100644 (file)
index 0000000..ee2e484
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.TokenSet;
+
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpSetOptions;
+import org.intellij.lang.regexp.psi.RegExpOptions;
+import org.intellij.lang.regexp.RegExpElementTypes;
+
+public class RegExpSetOptionsImpl extends RegExpElementImpl implements RegExpSetOptions {
+    public RegExpSetOptionsImpl(ASTNode astNode) {
+        super(astNode);
+    }
+
+    public RegExpOptions getOnOptions() {
+        final ASTNode[] nodes = getNode().getChildren(TokenSet.create(RegExpElementTypes.OPTIONS));
+        for (ASTNode node : nodes) {
+            if (!node.textContains('-')) {
+                return (RegExpOptions)node.getPsi();
+            }
+        }
+        return null;
+    }
+
+    public RegExpOptions getOffOptions() {
+        final ASTNode[] nodes = getNode().getChildren(TokenSet.create(RegExpElementTypes.OPTIONS));
+        for (ASTNode node : nodes) {
+            if (node.textContains('-')) {
+                return (RegExpOptions)node.getPsi();
+            }
+        }
+        return null;
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitRegExpSetOptions(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSimpleClassImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpSimpleClassImpl.java
new file mode 100644 (file)
index 0000000..63fbaf8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import org.jetbrains.annotations.NotNull;
+
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpSimpleClass;
+
+public class RegExpSimpleClassImpl extends RegExpElementImpl implements RegExpSimpleClass {
+    public RegExpSimpleClassImpl(ASTNode node) {
+        super(node);
+    }
+
+    @NotNull
+    public Kind getKind() {
+        final String s = getUnescapedText();
+        if (s.equals(".")) {
+            return Kind.ANY;
+        } else if (s.equals("\\d")) {
+            return Kind.DIGIT;
+        } else if (s.equals("\\D")) {
+            return Kind.NON_DIGIT;
+        } else if (s.equals("\\w")) {
+            return Kind.WORD;
+        } else if (s.equals("\\W")) {
+            return Kind.NON_WORD;
+        } else if (s.equals("\\s")) {
+            return Kind.SPACE;
+        } else if (s.equals("\\S")) {
+            return Kind.NON_SPACE;
+        }
+        assert false;
+        return null;
+    }
+
+    public void accept(RegExpElementVisitor visitor) {
+        visitor.visitSimpleClass(this);
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-filetype-icon.png b/RegExpSupport/src/org/intellij/lang/regexp/regexp-filetype-icon.png
new file mode 100644 (file)
index 0000000..f96a664
Binary files /dev/null and b/RegExpSupport/src/org/intellij/lang/regexp/regexp-filetype-icon.png differ
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex
new file mode 100644 (file)
index 0000000..a319ef6
--- /dev/null
@@ -0,0 +1,217 @@
+/* It's an automatically generated code. Do not modify it. */
+package org.intellij.lang.regexp;
+
+import com.intellij.lexer.FlexLexer;
+import com.intellij.psi.tree.IElementType;
+import java.util.LinkedList;
+import com.intellij.psi.StringEscapesTokenTypes;
+
+// IDEADEV-11055
+@SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" })
+%%
+
+%class _RegExLexer
+%implements FlexLexer
+%unicode
+%function advance
+%type IElementType
+%eof{  return;
+%eof}
+
+%{
+    // This adds support for nested states. I'm no JFlex pro, so maybe this is overkill, but it works quite well.
+    private final LinkedList<Integer> states = new LinkedList();
+
+    // This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax)
+    // as well, but is currently unfinished as it requires to tweak more places than just the lexer. 
+    private boolean xmlSchemaMode;
+
+    _RegExLexer(boolean xmlSchemaMode) {
+      this((java.io.Reader)null);
+      this.xmlSchemaMode = xmlSchemaMode;      
+    }
+
+    private void yypushstate(int state) {
+        states.addFirst(yystate());
+        yybegin(state);
+    }
+    private void yypopstate() {
+        final int state = states.removeFirst();
+        yybegin(state);
+    }
+
+    private void handleOptions() {
+      final String o = yytext().toString();
+      if (o.contains("x")) {
+        commentMode = !o.startsWith("-");
+      }
+    }
+
+    // tracks whether the lexer is in comment mode, i.e. whether whitespace is not significant and whether to ignore
+    // text after '#' till EOL
+    boolean commentMode = false;
+%}
+
+%xstate QUOTED
+%xstate EMBRACED
+%xstate CLASS1
+%state CLASS2
+%xstate OPTIONS
+%xstate COMMENT
+
+DIGITS=[1-9][0-9]*
+
+DOT="."
+LPAREN="("
+RPAREN=")"
+LBRACE="{"
+RBRACE="}"
+LBRACKET="["
+RBRACKET="]"
+
+ESCAPE="\\"
+ANY=.|\n
+
+META={ESCAPE} | {DOT} |
+  "^" | "$" | "?" | "*" | "+" | "|" |
+  {LBRACKET} | {LBRACE} | {LPAREN} | {RPAREN}
+
+CONTROL="t" | "n" | "r" | "f" | "a" | "e"
+BOUNDARY="b" | "B" | "A" | "z" | "Z" | "G"
+
+CLASS="w" | "W" | "s" | "S" | "d" | "D" | "X" | "C"
+XML_CLASS="c" | "C" | "i" | "I"
+PROP="p" | "P"
+
+HEX_CHAR=[0-9a-fA-F]
+
+%%
+
+"\\Q"                { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; }
+
+<QUOTED> {
+  "\\E"              { yypopstate(); return RegExpTT.QUOTE_END; }
+  .                  { return RegExpTT.CHARACTER; }
+}
+
+/* \\ */
+{ESCAPE} {ESCAPE}    { return RegExpTT.ESC_CHARACTER; }
+
+/* hex escapes */
+{ESCAPE} "x" {HEX_CHAR}{2}   { return RegExpTT.HEX_CHAR; }
+{ESCAPE} "x" {ANY}{0,2}      { return RegExpTT.BAD_HEX_VALUE; }
+
+/* unicode escapes */
+{ESCAPE} "u" {HEX_CHAR}{4}   { return RegExpTT.UNICODE_CHAR; }
+{ESCAPE} "u" {ANY}{0,4}      { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; }
+
+/* octal escapes */
+{ESCAPE} "0" [0-7]{1,3}      { return RegExpTT.OCT_CHAR; }
+{ESCAPE} "0"                 { return RegExpTT.BAD_OCT_VALUE; }
+
+/* single character after "\c" */
+{ESCAPE} "c" {ANY}           { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; }
+
+{ESCAPE} {XML_CLASS}         { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; }
+
+
+/* java.util.regex.Pattern says about backrefs:
+    "In this class, \1 through \9 are always interpreted as back references,
+    and a larger number is accepted as a back reference if at least that many
+    subexpressions exist at that point in the regular expression, otherwise the
+    parser will drop digits until the number is smaller or equal to the existing
+    number of groups or it is one digit."
+
+    So, for 100% compatibility, backrefs > 9 should be resolved by the parser, but
+    I'm not sure if it's worth the effort - at least not atm.
+*/
+      
+{ESCAPE} {DIGITS}             { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; }
+
+{ESCAPE}  "-"                 { return RegExpTT.ESC_CHARACTER; }
+{ESCAPE}  {META}              { return RegExpTT.ESC_CHARACTER; }
+{ESCAPE}  {CLASS}             { return RegExpTT.CHAR_CLASS;    }
+{ESCAPE}  {PROP}              { return RegExpTT.PROPERTY;      }
+
+{ESCAPE}  {BOUNDARY}          { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; }
+{ESCAPE}  {CONTROL}           { return RegExpTT.ESC_CTRL_CHARACTER; }
+
+{ESCAPE}  [:letter:]          { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; }
+{ESCAPE}  {ANY}               { return RegExpTT.REDUNDANT_ESCAPE; }
+
+/* "{" \d+(,\d*)? "}" */
+/* "}" outside counted closure is treated as regular character */
+{LBRACE}              { yypushstate(EMBRACED); return RegExpTT.LBRACE; }
+
+<EMBRACED> {
+  [:letter:]+         { return RegExpTT.NAME;   }
+  [:digit:]+          { return RegExpTT.NUMBER; }
+  ","                 { return RegExpTT.COMMA;  }
+
+  {RBRACE}            { yypopstate(); return RegExpTT.RBRACE; }
+  {ANY}               { return RegExpTT.BAD_CHARACTER; }
+}
+
+"-"                   { return RegExpTT.MINUS; }
+"^"                   { return RegExpTT.CARET; }
+
+{LBRACKET} / {RBRACKET}   { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; }
+{LBRACKET}                { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; }
+
+/* []abc] is legal. The first ] is treated as literal character */
+<CLASS1> {
+  {RBRACKET}              { yybegin(CLASS2); return RegExpTT.CHARACTER; }
+  .                       { assert false : yytext(); }
+}
+
+<CLASS2> {
+  {RBRACKET}            { yypopstate(); return RegExpTT.CLASS_END; }
+
+  "&&"                  { return RegExpTT.ANDAND;    }
+  {ANY}                 { return RegExpTT.CHARACTER; }
+}
+
+<YYINITIAL> {
+  {LPAREN}      { return RegExpTT.GROUP_BEGIN; }
+  {RPAREN}      { return RegExpTT.GROUP_END;   }
+
+  "|"           { return RegExpTT.UNION;  }
+  "?"           { return RegExpTT.QUEST;  }
+  "*"           { return RegExpTT.STAR;   }
+  "+"           { return RegExpTT.PLUS;   }
+  "$"           { return RegExpTT.DOLLAR; }
+  {DOT}         { return RegExpTT.DOT;    }
+
+  "(?:"       { return RegExpTT.NON_CAPT_GROUP;  }
+  "(?="       { return RegExpTT.POS_LOOKAHEAD;   }
+  "(?!"       { return RegExpTT.NEG_LOOKAHEAD;   }
+  "(?<="      { return RegExpTT.POS_LOOKBEHIND;  }
+  "(?<!"      { return RegExpTT.NEG_LOOKBEHIND;  }
+
+  "(?"        { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; }
+}
+
+<OPTIONS> {
+  [:letter:]*         { handleOptions(); return RegExpTT.OPTIONS_ON; }
+  ("-" [:letter:]*)   { handleOptions(); return RegExpTT.OPTIONS_OFF; }
+
+  ":"               { yybegin(YYINITIAL); return RegExpTT.COLON;  }
+  ")"               { yybegin(YYINITIAL); return RegExpTT.GROUP_END; }
+
+  {ANY}             { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; }
+}
+
+/* "dangling ]" */
+<YYINITIAL> {RBRACKET}    { return RegExpTT.CHARACTER; }
+
+
+"#"           { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; }
+<COMMENT> {
+  [^\r\n]*[\r\n]?  { yypopstate(); return RegExpTT.COMMENT; }
+}
+
+" "          { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; }
+[\b\t\r\f]   { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; }
+\n           { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; }
+
+{ANY}        { return RegExpTT.CHARACTER; }
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/surroundWith/GroupSurrounder.java b/RegExpSupport/src/org/intellij/lang/regexp/surroundWith/GroupSurrounder.java
new file mode 100644 (file)
index 0000000..7e0dde2
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.surroundWith;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.surroundWith.Surrounder;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.PsiLiteralExpression;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.intellij.lang.regexp.RegExpFileType;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+import org.intellij.lang.regexp.psi.impl.RegExpElementImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class GroupSurrounder implements Surrounder {
+    private final String myTitle;
+    private final String myGroupStart;
+
+    public GroupSurrounder(String title, String groupStart) {
+        myTitle = title;
+        myGroupStart = groupStart;
+    }
+
+    public String getTemplateDescription() {
+        return myTitle;
+    }
+
+    public boolean isApplicable(@NotNull PsiElement[] elements) {
+        return elements.length == 1 || PsiTreeUtil.findCommonParent(elements) == elements[0].getParent();
+    }
+
+    @Nullable
+    public TextRange surroundElements(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) throws IncorrectOperationException {
+        assert elements.length == 1 || PsiTreeUtil.findCommonParent(elements) == elements[0].getParent();
+        final PsiElement e = elements[0];
+        final ASTNode node = e.getNode();
+        assert node != null;
+
+        final ASTNode parent = node.getTreeParent();
+
+        final StringBuilder s = new StringBuilder();
+        for (int i = 0; i < elements.length; i++) {
+            final PsiElement element = elements[i];
+            if (element instanceof RegExpElementImpl) {
+                s.append(((RegExpElementImpl)element).getUnescapedText());
+            } else {
+                s.append(element.getText());
+            }
+            if (i > 0) {
+                final ASTNode child = element.getNode();
+                assert child != null;
+                parent.removeChild(child);
+            }
+        }
+        final PsiFileFactory factory = PsiFileFactory.getInstance(project);
+
+        final PsiFile f = factory.createFileFromText("dummy.regexp", RegExpFileType.INSTANCE, makeReplacement(s));
+        final RegExpPattern pattern = PsiTreeUtil.getChildOfType(f, RegExpPattern.class);
+        assert pattern != null;
+
+        final RegExpAtom element = pattern.getBranches()[0].getAtoms()[0];
+
+        if (isInsideStringLiteral(e)) {
+            final Document doc = editor.getDocument();
+            final TextRange tr = e.getTextRange();
+            doc.replaceString(tr.getStartOffset(), tr.getEndOffset(),
+                    StringUtil.escapeStringCharacters(element.getText()));
+
+            return TextRange.from(e.getTextRange().getEndOffset(), 0);
+        } else {
+            final PsiElement n = e.replace(element);
+            return TextRange.from(n.getTextRange().getEndOffset(), 0);
+        }
+    }
+
+    private static boolean isInsideStringLiteral(PsiElement context) {
+        return PsiTreeUtil.getContextOfType(context, PsiLiteralExpression.class, false) != null;
+    }
+
+    protected String makeReplacement(StringBuilder s) {
+        return myGroupStart + s + ")";
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/surroundWith/SimpleSurroundDescriptor.java b/RegExpSupport/src/org/intellij/lang/regexp/surroundWith/SimpleSurroundDescriptor.java
new file mode 100644 (file)
index 0000000..94e35dc
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.surroundWith;
+
+import com.intellij.lang.surroundWith.SurroundDescriptor;
+import com.intellij.lang.surroundWith.Surrounder;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import org.intellij.lang.regexp.psi.RegExpElement;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+import org.intellij.lang.regexp.psi.RegExpBranch;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SimpleSurroundDescriptor implements SurroundDescriptor {
+    private static final Surrounder[] SURROUNDERS = {
+            new GroupSurrounder("Capturing Group (pattern)", "("),
+            new GroupSurrounder("Non-Capturing Group (?:pattern)", "(?:"),
+    };
+
+    @NotNull
+    public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
+        return findElementsInRange(file, startOffset, endOffset);
+    }
+
+    @NotNull
+    public Surrounder[] getSurrounders() {
+        return SURROUNDERS;
+    }
+
+    private PsiElement[] findElementsInRange(PsiFile file, int startOffset, int endOffset) {
+        // adjust start/end
+        PsiElement element1 = file.findElementAt(startOffset);
+        PsiElement element2 = file.findElementAt(endOffset - 1);
+        if (element1 instanceof PsiWhiteSpace) {
+            startOffset = element1.getTextRange().getEndOffset();
+        }
+        if (element2 instanceof PsiWhiteSpace) {
+            endOffset = element2.getTextRange().getStartOffset();
+        }
+
+        final RegExpElement pattern = findElementAtStrict(file, startOffset, endOffset, RegExpPattern.class);
+        if (pattern != null) return new RegExpElement[]{ pattern };
+
+        final RegExpElement branch = findElementAtStrict(file, startOffset, endOffset, RegExpBranch.class);
+        if (branch != null) return new RegExpElement[]{ branch };
+
+        final List<PsiElement> atoms = new ArrayList<PsiElement>();
+        RegExpAtom atom = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, RegExpAtom.class);
+        for (; atom != null; atom = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, RegExpAtom.class)) {
+            atoms.add(atom);
+            startOffset = atom.getTextRange().getEndOffset();
+
+            // handle embedded whitespace
+            if ((element1 = file.findElementAt(startOffset)) instanceof PsiWhiteSpace) {
+                startOffset = element1.getTextRange().getEndOffset();
+                atoms.add(element1);
+            }
+        }
+
+        if (startOffset == endOffset && atoms.size() > 0) {
+            final PsiElement[] elements = atoms.toArray(new PsiElement[atoms.size()]);
+            if ((atoms.size() == 1 || PsiTreeUtil.findCommonParent(elements) == elements[0].getParent())) {
+                return elements;
+            }
+        }
+        return PsiElement.EMPTY_ARRAY;
+    }
+
+    @Nullable
+    private static <T extends RegExpElement> T findElementAtStrict(PsiFile file, int startOffset, int endOffset, Class<T> clazz) {
+        T element = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, clazz);
+        if (element == null || element.getTextRange().getEndOffset() < endOffset) return null;
+        return element;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java b/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java
new file mode 100644 (file)
index 0000000..b0415f3
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.validation;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.annotation.Annotation;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.Annotator;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.psi.RegExpAtom;
+import org.intellij.lang.regexp.psi.RegExpBackref;
+import org.intellij.lang.regexp.psi.RegExpBranch;
+import org.intellij.lang.regexp.psi.RegExpChar;
+import org.intellij.lang.regexp.psi.RegExpCharRange;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.intellij.lang.regexp.psi.RegExpGroup;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+import org.intellij.lang.regexp.psi.RegExpProperty;
+import org.intellij.lang.regexp.psi.RegExpQuantifier;
+import org.intellij.lang.regexp.psi.impl.RegExpPropertyImpl;
+
+public final class RegExpAnnotator extends RegExpElementVisitor implements Annotator {
+    private AnnotationHolder myHolder;
+
+    // made this synchronized after running into the assertion below a couple of times.
+    public synchronized void annotate(PsiElement psiElement, AnnotationHolder holder) {
+        assert myHolder == null : "unsupported concurrent annotator invocation";
+        try {
+            myHolder = holder;
+            psiElement.accept(this);
+        } finally {
+            myHolder = null;
+        }
+    }
+
+    public void visitRegExpCharRange(RegExpCharRange range) {
+        final RegExpCharRange.Endpoint from = range.getFrom();
+        final RegExpCharRange.Endpoint to = range.getTo();
+        final boolean a = from instanceof RegExpChar;
+        final boolean b = to instanceof RegExpChar;
+        if (a && b) {
+            final Character t = ((RegExpChar)to).getValue();
+            final Character f = ((RegExpChar)from).getValue();
+            if (t != null && f != null) {
+                if (t < f) {
+                    myHolder.createErrorAnnotation(range, "Illegal character range (to < from)");
+                } else if (t == f) {
+                    myHolder.createWarningAnnotation(range, "Redundant character range");
+                }
+            }
+        } else if (a != b) {
+            myHolder.createErrorAnnotation(range, "Character class (e.g. '\\\\w') may not be used inside character range");
+        } else if (from.getText().equals(to.getText())) {
+            myHolder.createWarningAnnotation(range, "Redundant character range");
+        }
+    }
+
+    public void visitRegExpChar(final RegExpChar ch) {
+       final Character value = ch.getValue();
+        if (value == null) {
+            switch (ch.getType()) {
+                case CHAR:
+                    myHolder.createErrorAnnotation(ch, "Illegal/unsupported escape sequence");
+                    break;
+                case HEX:
+                    myHolder.createErrorAnnotation(ch, "Illegal hexadecimal escape sequence");
+                    break;
+                case OCT:
+                    myHolder.createErrorAnnotation(ch, "Illegal octal escape sequence");
+                    break;
+                case UNICODE:
+                    myHolder.createErrorAnnotation(ch, "Illegal unicode escape sequence");
+                    break;
+            }
+        } else {
+            final String text = ch.getUnescapedText();
+            if (text.startsWith("\\") && !("\\]".equals(text) || "\\}".equals(text))) {
+                final ASTNode astNode = ch.getNode().getFirstChildNode();
+                if (astNode != null && astNode.getElementType() == RegExpTT.REDUNDANT_ESCAPE) {
+                    final Annotation a = myHolder.createInformationAnnotation(ch, "Redundant character escape");
+                    registerFix(a, new RemoveRedundantEscapeAction(ch));
+                }
+            }
+        }
+    }
+
+    public void visitRegExpProperty(RegExpProperty property) {
+        final ASTNode category = property.getCategoryNode();
+        if (category != null && !RegExpPropertyImpl.isValidCategory(category.getText())) {
+            final Annotation a = myHolder.createErrorAnnotation(category, "Unknown character category");
+            if (a != null) {
+                // IDEA-9381
+                a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+            }
+        }
+    }
+
+    public void visitRegExpBackref(final RegExpBackref backref) {
+        final RegExpGroup group = backref.resolve();
+        if (group == null) {
+            final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved backreference");
+            if (a != null) {
+                // IDEA-9381
+                a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+            }
+        } else if (PsiTreeUtil.isAncestor(group, backref, true)) {
+            myHolder.createWarningAnnotation(backref, "Backreference is nested into the capturing group it refers to");
+        }
+    }
+
+    public void visitRegExpGroup(RegExpGroup group) {
+        final RegExpPattern pattern = group.getPattern();
+        if (pattern != null) {
+            final RegExpBranch[] branches = pattern.getBranches();
+            if (isEmpty(branches)) {
+                // catches "()" as well as "(|)"
+                myHolder.createWarningAnnotation(group, "Empty group");
+            } else if (branches.length == 1) {
+                final RegExpAtom[] atoms = branches[0].getAtoms();
+                if (atoms.length == 1 && atoms[0] instanceof RegExpGroup) {
+                    myHolder.createWarningAnnotation(group, "Redundant group nesting");
+                }
+            }
+        }
+    }
+
+    private static boolean isEmpty(RegExpBranch[] branches) {
+        for (RegExpBranch branch : branches) {
+            if (branch.getAtoms().length > 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void visitRegExpQuantifier(RegExpQuantifier quantifier) {
+        final RegExpQuantifier.Count count = quantifier.getCount();
+        if (!(count instanceof RegExpQuantifier.SimpleCount)) {
+            final int min = count.getMin();
+            final int max = count.getMax();
+            if (max < min) {
+                myHolder.createErrorAnnotation(quantifier, "Illegal repetition range");
+            } else if (max == min) {
+                if (max == 1) { // TODO: is this safe when relucant or possesive modifier is present?
+                    final Annotation a = myHolder.createInformationAnnotation(quantifier, "Single repetition");
+                    registerFix(a, new SimplifyQuantifierAction(quantifier, null));
+                } else {
+                    final ASTNode node = quantifier.getNode();
+                    if (node.findChildByType(RegExpTT.COMMA) != null) {
+                        final Annotation a = myHolder.createInformationAnnotation(quantifier, "Fixed repetition range");
+                        registerFix(a, new SimplifyQuantifierAction(quantifier, "{" + max + "}"));
+                    }
+                }
+            } else if (min == 0 && max == 1) {
+                final Annotation a = myHolder.createInformationAnnotation(quantifier, "Repetition range replaceable by '?'");
+                registerFix(a, new SimplifyQuantifierAction(quantifier, "?"));
+            } else if (min == 0 && max == Integer.MAX_VALUE) {
+                final Annotation a = myHolder.createInformationAnnotation(quantifier, "Repetition range replaceable by '*'");
+                registerFix(a, new SimplifyQuantifierAction(quantifier, "*"));
+            } else if (min == 1 && max == Integer.MAX_VALUE) {
+                final Annotation a = myHolder.createInformationAnnotation(quantifier, "Repetition range replaceable by '+'");
+                registerFix(a, new SimplifyQuantifierAction(quantifier, "+"));
+            }
+        }
+    }
+
+    private static void registerFix(Annotation a, IntentionAction action) {
+        if (a != null) {
+            // IDEA-9381
+            a.registerFix(action);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/validation/RemoveRedundantEscapeAction.java b/RegExpSupport/src/org/intellij/lang/regexp/validation/RemoveRedundantEscapeAction.java
new file mode 100644 (file)
index 0000000..dfb4579
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.validation;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiLiteralExpression;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlStringUtil;
+import com.intellij.lang.ASTNode;
+import org.intellij.lang.regexp.psi.RegExpChar;
+import org.intellij.lang.regexp.RegExpTT;
+import org.jetbrains.annotations.NotNull;
+
+class RemoveRedundantEscapeAction implements IntentionAction {
+    private final RegExpChar myChar;
+
+    public RemoveRedundantEscapeAction(RegExpChar ch) {
+        myChar = ch;
+    }
+
+    @NotNull
+    public String getText() {
+        return "Remove Redundant Escape";
+    }
+
+    @NotNull
+    public String getFamilyName() {
+        return "Redundant Character Escape";
+    }
+
+    public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+        return myChar.isValid() && myChar.getUnescapedText().startsWith("\\");
+    }
+
+    public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+        final Character v = myChar.getValue();
+        assert v != null;
+
+        final ASTNode node = myChar.getNode();
+        final ASTNode parent = node.getTreeParent();
+        parent.addLeaf(RegExpTT.CHARACTER, replacement(v), node);
+        parent.removeChild(node);
+    }
+
+    private String replacement(Character v) {
+        final PsiElement context = myChar.getContainingFile().getContext();
+        return context instanceof PsiLiteralExpression ?
+                StringUtil.escapeStringCharacters(v.toString()) :
+                (context instanceof XmlElement ?
+                        XmlStringUtil.escapeString(v.toString()) :
+                        v.toString());
+    }
+
+    public boolean startInWriteAction() {
+        return true;
+    }
+}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/validation/SimplifyQuantifierAction.java b/RegExpSupport/src/org/intellij/lang/regexp/validation/SimplifyQuantifierAction.java
new file mode 100644 (file)
index 0000000..812da5e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.validation;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.intellij.lang.regexp.RegExpFileType;
+import org.intellij.lang.regexp.psi.RegExpClosure;
+import org.intellij.lang.regexp.psi.RegExpPattern;
+import org.intellij.lang.regexp.psi.RegExpQuantifier;
+import org.jetbrains.annotations.NotNull;
+
+class SimplifyQuantifierAction implements IntentionAction {
+    private final RegExpQuantifier myQuantifier;
+    private final String myReplacement;
+
+    public SimplifyQuantifierAction(RegExpQuantifier quantifier, String s) {
+        myQuantifier = quantifier;
+        myReplacement = s;
+    }
+
+    @NotNull
+    public String getText() {
+        return myReplacement == null ? "Simplify" : "Replace with '" + myReplacement + "'";
+    }
+
+    @NotNull
+    public String getFamilyName() {
+        return "Simplify Quantifier";
+    }
+
+    public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+        return myQuantifier.isValid();
+    }
+
+    public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+        if (myReplacement == null) {
+            myQuantifier.delete();
+        } else {
+            final PsiFileFactory factory = PsiFileFactory.getInstance(project);
+
+            final PsiFile f = factory.createFileFromText("dummy.regexp", RegExpFileType.INSTANCE, "a" + myReplacement + myQuantifier.getType().getToken());
+            final RegExpPattern pattern = PsiTreeUtil.getChildOfType(f, RegExpPattern.class);
+            assert pattern != null;
+
+            final RegExpClosure closure = (RegExpClosure)pattern.getBranches()[0].getAtoms()[0];
+            myQuantifier.replace(closure.getQuantifier());
+        }
+    }
+
+    public boolean startInWriteAction() {
+        return true;
+    }
+}
diff --git a/RegExpSupport/test/test/BaseParseTestcase.java b/RegExpSupport/test/test/BaseParseTestcase.java
new file mode 100644 (file)
index 0000000..bd95a17
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test;
+
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
+import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
+import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.testFramework.fixtures.TestFixtureBuilder;
+
+import junit.framework.TestCase;
+import org.intellij.lang.regexp.RegExpFileType;
+
+public class BaseParseTestcase extends TestCase {
+    protected CodeInsightTestFixture myFixture;
+
+    protected void setUp() throws Exception {
+        final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
+        final TestFixtureBuilder<IdeaProjectTestFixture> builder = fixtureFactory.createLightFixtureBuilder();
+
+        final IdeaProjectTestFixture projectFixture = builder.getFixture();
+        projectFixture.setUp();
+
+        final CodeInsightTestFixture fixture = fixtureFactory.createCodeInsightFixture(projectFixture);
+        fixture.setTestDataPath(getTestDataPath());
+        fixture.setUp();
+
+        final Project project = projectFixture.getProject();
+
+        new WriteCommandAction(project) {
+            protected void run(Result result) throws Throwable {
+                FileTypeManager.getInstance().registerFileType(RegExpFileType.INSTANCE, new String[]{ "regexp" });
+            }
+        }.execute();
+
+        myFixture = fixture;
+    }
+
+    protected String getTestDataPath() {
+        return "testData/psi/";
+    }
+
+    protected void tearDown() throws Exception {
+        myFixture.tearDown();
+    }
+}
diff --git a/RegExpSupport/test/test/Main.java b/RegExpSupport/test/test/Main.java
new file mode 100644 (file)
index 0000000..e248d81
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test;
+
+import java.util.regex.Pattern;
+
+@SuppressWarnings({ "ALL" })
+public class Main {
+    public static void main(String[] args) {
+        final Pattern pattern = Pattern.compile("[\\b]");
+    }
+}
diff --git a/RegExpSupport/test/test/MainParseTest.java b/RegExpSupport/test/test/MainParseTest.java
new file mode 100644 (file)
index 0000000..53bc895
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.application.PathManager;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.jdom.xpath.XPath;
+
+import java.io.*;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class MainParseTest extends BaseParseTestcase {
+
+    private static final File OUT = new File("testData/psi/gen");
+    private ByteArrayOutputStream myOut;
+
+    enum Result {
+        OK, ERR
+    }
+    class Test {
+        boolean showWarnings = true;
+        boolean showInfo = false;
+        Result expectedResult;
+
+        Test(Result result, boolean warn, boolean info) {
+            expectedResult = result;
+            showWarnings = warn;
+            showInfo = info;
+        }
+    }
+
+    private Map<String, Test> myMap = new LinkedHashMap<String, Test>();
+
+    protected void setUp() throws Exception {
+        final Document document = new SAXBuilder().build(new File(PathManager.getPluginsPath()+"/RegExpSupport/testData/RETest.xml"));
+        final List<Element> list = XPath.selectNodes(document.getRootElement(), "//test");
+        OUT.mkdirs();
+
+        int i = 0;
+        for (Element element : list) {
+            final String name;
+            final String s = ((Element)element.getParent()).getName();
+            if (!"tests".equals(s)) {
+                name = s + "/test-" + ++i + ".regexp";
+            } else {
+                name = "test-" + ++i + ".regexp";
+            }
+            final Result result = Result.valueOf((String)XPath.selectSingleNode(element, "string(expected)"));
+            final boolean warn = !"false".equals(element.getAttributeValue("warning"));
+            final boolean info = "true".equals(element.getAttributeValue("info"));
+            myMap.put(name, new Test(result, warn, info));
+
+            final File file = new File(OUT, name);
+            file.getParentFile().mkdirs();
+
+            final FileWriter stream = new FileWriter(file);
+            final String pattern = (String)XPath.selectSingleNode(element, "string(pattern)");
+            if (!"false".equals(element.getAttributeValue("verify"))) try {
+                Pattern.compile(pattern);
+                if (result == Result.ERR) {
+                    System.out.println("Incorrect FAIL value for " + pattern);
+                }
+            } catch (PatternSyntaxException e) {
+                if (result == Result.OK) {
+                    System.out.println("Incorrect OK value for " + pattern);
+                }
+            }
+            stream.write(pattern);
+            stream.close();
+        }
+
+        super.setUp();
+
+        myOut = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(myOut));
+    }
+
+    protected String getTestDataPath() {
+        return OUT.getPath() + "/";
+    }
+
+    public void testSimple() throws Exception {
+        doTest("simple/");
+    }
+
+    public void testQuantifiers() throws Exception {
+        doTest("quantifiers/");
+    }
+
+    public void testGroups() throws Exception {
+        doTest("groups/");
+    }
+
+    public void testCharclasses() throws Exception {
+        doTest("charclasses/");
+    }
+
+    public void testEscapes() throws Exception {
+        doTest("escapes/");
+    }
+
+    public void testAnchors() throws Exception {
+        doTest("anchors/");
+    }
+
+    public void testNamedchars() throws Exception {
+        doTest("namedchars/");
+    }
+
+    public void testBackrefs() throws Exception {
+        doTest("backrefs/");
+    }
+
+    public void testComplex() throws Exception {
+        doTest("complex/");
+    }
+
+    public void testIncomplete() throws Exception {
+        doTest("incomplete/");
+    }
+
+    public void testRealLife() throws Exception {
+        doTest("real-life/");
+    }
+
+    public void testRegressions() throws Exception {
+        doTest("regressions/");
+    }
+
+    public void testFromXML() throws Exception {
+        doTest(null);
+    }
+
+    private void doTest(String prefix) throws IOException {
+        int n = 0, failed = 0;
+        for (String name : myMap.keySet()) {
+            if (prefix == null && name.contains("/")) {
+                continue;
+            }
+            if (prefix != null && !name.startsWith(prefix)) {
+                continue;
+            }
+            System.out.print("filename = " + name);
+            n++;
+
+            final MainParseTest.Test test = myMap.get(name);
+            try {
+                myFixture.testHighlighting(test.showWarnings, true, test.showInfo, name);
+
+                if (test.expectedResult == Result.ERR) {
+                    System.out.println("  FAILED. Expression incorrectly parsed OK: " + FileUtil.loadTextAndClose(new FileReader(new File(OUT, name))));
+                    failed++;
+                } else {
+                    System.out.println("  OK");
+                }
+            } catch (Throwable e) {
+                if (test.expectedResult == Result.ERR) {
+                    System.out.println("  OK");
+                } else {
+                    System.out.println("  FAILED. Expression = " + FileUtil.loadTextAndClose(new FileReader(new File(OUT, name))));
+                    if (myOut.size() > 0) {
+                        String line;
+                        final BufferedReader reader = new BufferedReader(new StringReader(myOut.toString()));
+                        do {
+                            line = reader.readLine();
+                        } while (line != null && (line.trim().length() == 0 || line.trim().equals("ERROR:")));
+                        if (line != null) {
+                            if (line.matches(".*java.lang.Error: junit.framework.AssertionFailedError:.*")) {
+                                System.out.println("ERROR: " + line.replace("java.lang.Error: junit.framework.AssertionFailedError:", ""));
+                            }
+                        } else {
+                            System.out.println("ERROR: " + myOut.toString());
+                        }
+                    }
+                    failed++;
+                }
+            }
+            myOut.reset();
+        }
+
+        System.out.println("");
+        System.out.println(n + " Tests executed, " + failed + " failed");
+
+        assertFalse(failed > 0);
+    }
+}
diff --git a/RegExpSupport/test/test/ParseTest.java b/RegExpSupport/test/test/ParseTest.java
new file mode 100644 (file)
index 0000000..55880e5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Sascha Weinreuter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test;
+
+public class ParseTest extends BaseParseTestcase {
+
+    public void test0() throws Throwable {
+        myFixture.testHighlighting("test0.regexp");
+    }
+    public void test1() throws Throwable {
+        myFixture.testHighlighting("test1.regexp");
+    }
+    public void test2() throws Throwable {
+        myFixture.testHighlighting("test2.regexp");
+    }
+    public void test3() throws Throwable {
+        myFixture.testHighlighting("test3.regexp");
+    }
+    public void test4() throws Throwable {
+        myFixture.testHighlighting("test4.regexp");
+    }
+}
diff --git a/RegExpSupport/testData/RETest.xml b/RegExpSupport/testData/RETest.xml
new file mode 100644 (file)
index 0000000..4e2d33f
--- /dev/null
@@ -0,0 +1,931 @@
+<tests>
+  <simple>
+    <test>
+      <pattern>|</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(|\$.*)\.class</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>abc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>multiple words of text</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab|cd</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab*c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab*bc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab+bc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab?bc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>ab?c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a.c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a.*c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>*a</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Single repetition">{1}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a{</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{1,}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{1,2}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{1,foo}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test info="true" verify="false">
+      <pattern><![CDATA[<weak_warning descr="Redundant character escape">\;</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+  </simple>
+  <quantifiers>
+    <test>
+      <pattern>a?</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a??</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a+?</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a*?</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a?+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a++</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a*+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a**</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a{2}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{1,2}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{2,1}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Repetition range replaceable by '?'">{0,1}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Repetition range replaceable by '+'">{1,}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Repetition range replaceable by '*'">{0,}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Single repetition">{1}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false" info="true">
+      <pattern><![CDATA[a<weak_warning descr="Fixed repetition range">{3,3}</weak_warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a{}</pattern>
+      <expected>ERR</expected>
+    </test>
+  </quantifiers>
+  <charclasses>
+    <test>
+      <pattern>a[bc]d</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b-d]e</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b-d]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b-a]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a[-b]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b-]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-[b]]</pattern>
+      <expected jdk="OK">OK</expected>
+    </test>
+    <test>
+      <pattern>a[b&amp;&amp;[cd]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b-&amp;&amp;[cd]]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a[b&amp;&amp;-]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b&amp;&amp;-b]</pattern>
+      <expected jdk="OK">OK</expected>
+    </test>
+    <test>
+      <pattern>[&amp;&amp;]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a[b&amp;&amp;c&amp;&amp;d]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[b&amp;&amp;c&amp;&amp;d-e&amp;&amp;f]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[a[b][c]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-[]]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>[a-[b</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>[a[^b]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[a[b[c]][d]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[\t--]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[\t--]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[\t---]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[-]?c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-[</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a[]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[^bc]d</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[^bc]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[]b</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>[abhgefdc]ij</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-zA-Z_][a-zA-Z0-9_]*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([a-c]+?)c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([ab]*?)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([ab]*)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([ab]??)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(c[ab]?)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(c[ab]??)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(c[ab]*?)b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[bcd]+dcdcde</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[k]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[bcd]*dcdcde</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[^ab]*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[.]b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[+*?]b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a[\p{IsDigit}\p{IsAlpha}]b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[\p{L}&amp;&amp;[^\p{Lu}]]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a\p</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a\p{}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a\p}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a\p{123}</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[[<warning descr="Redundant character range">\w-\w</warning>]]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-\w]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>(?x)abc #foo \q bar
+# foo
+(?-xi)xyz(?i:ABC)</pattern>
+      <expected>OK</expected>
+    </test>
+  </charclasses>
+
+  <groups>
+    <test warning="false">
+      <pattern>()ef</pattern>
+      <expected>OK</expected>
+    </test>
+    <test warning="false">
+      <pattern>()*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[<warning descr="Empty group">()</warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[<warning descr="Empty group">(|)</warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(*)b</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[<warning descr="Redundant group nesting">((a))</warning>]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a)b(c)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a*)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a*)+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a|)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(ab|cd)e</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(.*)c(.*)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\((.*), (.*)\)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a(bc)d</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([abc])*d</pattern>
+      <expected>OK</expected>
+    </test>
+    <test warning="false">
+      <pattern>((((((((((a)))))))))</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>([abc])*bcd</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a|b)c*d</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a([bc]*)c*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>((a)(b)c)(d)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(ab|a)b*c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(ab|ab*)bc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a|b|c|d|e)f</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a([bc]*)(c*d)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a([bc]+)(c*d)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a([bc]*)(c+d)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a+|b)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a+|b)+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a+|b)?</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(^*</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>)(</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>(?i:*)</pattern>
+      <expected>ERR</expected>
+    </test>
+  </groups>
+  <escapes>
+    <test>
+      <pattern>\q</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>\#</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a\</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a\(b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a\(*b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a\\b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\u004a</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\0123</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\0</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>\x4a</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[\x4a-\x4b]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[[<warning descr="Redundant character range">a-a</warning>]]]></pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[\x4a-\x3f]</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>a\Qabc?*+.))]][]\Eb</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(a\Qabc?*+.))]][]\Eb)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[\Qabc?*+.))]][]\E]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>a\Qabc?*+.))]][]\E)</pattern>
+      <expected>ERR</expected>
+    </test>
+  </escapes>
+
+  <anchors>
+    <test>
+      <pattern>^*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>$*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^abc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^abc$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>abc$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>$b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^(ab|cd)e</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^a(bc+|b[eh])g|.h$</pattern>
+      <expected>OK</expected>
+    </test>
+  </anchors>
+  <namedchars>
+    <test>
+      <pattern>a*b\s+c</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\d+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^\p{javaJavaIdentifierStart}+\p{javaJavaIdentifierPart}+$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\p{IsDigit}\p{IsAlpha}</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[a-e]?d\\e</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>((\w+)/)*(\w+)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\p{Digit}+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>[:xdigit:]+</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\p{unknown}+</pattern>
+      <expected>ERR</expected>
+    </test>
+  </namedchars>
+  <backrefs>
+    <test>
+      <pattern>(ac*)c*d[ac]*\1</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(.)=\1</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([ab])=\1</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>([ab]+)=\1</pattern>
+      <expected>OK</expected>
+    </test>
+    <test verify="false">
+      <pattern>([ab]+)=\2</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>([ab]+)=\3</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test verify="false">
+      <pattern><![CDATA[([ab]+=<warning descr="Backreference is nested into the capturing group it refers to">\1</warning>)]]></pattern>
+      <expected>OK</expected>
+    </test>
+  </backrefs>
+  <complex>
+    <test>
+      <pattern>z(\w\s+(?:\w\s+\w)+)z</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>((?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(?:([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^(?:([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$</pattern>
+      <expected>OK</expected>
+    </test>
+  </complex>
+
+  <incomplete>
+    <test>
+      <pattern>abc\</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>abc[\</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>abc\x</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>abc\x1</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>abc\u</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>abc\u22</pattern>
+      <expected>ERR</expected>
+    </test>
+    <test>
+      <pattern>\Qabc</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\Q</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\E</pattern>
+      <expected>ERR</expected>
+    </test>
+  </incomplete>
+
+  <regressions>
+    <!-- caused NPE in Annotator -->
+    <test>
+      <pattern>(</pattern>
+      <expected>ERR</expected>
+    </test>
+    <!-- broke by TokenType modifications -->
+    <test>
+      <pattern>[^^]</pattern>
+      <expected>OK</expected>
+    </test>
+  </regressions>
+
+  <test>
+    <pattern>abc)</pattern>
+    <expected>ERR</expected>
+  </test>
+  <test>
+    <pattern>(abc</pattern>
+    <expected>ERR</expected>
+  </test>
+  <test>
+    <pattern>a+b+c</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a**</pattern>
+    <expected>ERR</expected>
+  </test>
+  <test>
+    <pattern>a++</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>ab*</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>abcd*efg</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a|b|c|d|e</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(bc+d$|ef*g.|h?i(j|k))</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a*(b*c*)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a?b+c*</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>i am a green (giant|man|martian)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(wee|week)(knights|knight)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(a.*b)(a.*b)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(\s*\w+)?</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(?:a)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(?:\w)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(?:\w\s\w)+</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>(a\w)(?:,(a\w))+</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>abc.*?x+yz</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>abc.+?x+yz</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a.+?(c|d)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a.+(c|d)</pattern>
+    <expected>OK</expected>
+  </test>
+  <test>
+    <pattern>a+?b+?c+?</pattern>
+    <expected>OK</expected>
+  </test>
+  <real-life>
+    <test>
+      <pattern>x:found="(true|false)"</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(?:\s)|(?:/\*.*\*/)|(?://[^\n]*)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>((?:\p{Alpha}\:)?[0-9 a-z_A-Z\-\\./]+)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^[\w\+\.\-]{2,}:</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>#(.*)$</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>usd [+-]?[0-9]+.[0-9][0-9]</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>\b(\w+)(\s+\1)+\b</pattern>
+      <expected>OK</expected>
+    </test>
+    <test>
+      <pattern>.*?(&lt;(error|warning|info)(?: descr="((?:[^"\\]|\\")*)")?(?: type="([0-9A-Z_]+)")?(?: foreground="([0-9xa-f]+)")?(?: background="([0-9xa-f]+)")?(?: effectcolor="([0-9xa-f]+)")?(?: effecttype="([A-Z]+)")?(?: fonttype="([0-9]+)")?(/)?>)(.*)</pattern>
+      <expected>OK</expected>
+    </test>
+  </real-life>
+</tests>
diff --git a/RegExpSupport/testData/psi/test1.regexp b/RegExpSupport/testData/psi/test1.regexp
new file mode 100644 (file)
index 0000000..0e3e0f8
--- /dev/null
@@ -0,0 +1 @@
+123 | 456
\ No newline at end of file
diff --git a/RegExpSupport/testData/psi/test2.regexp b/RegExpSupport/testData/psi/test2.regexp
new file mode 100644 (file)
index 0000000..3de5e49
--- /dev/null
@@ -0,0 +1 @@
+1*<error descr="Dangling metacharacter">*</error>
\ No newline at end of file
diff --git a/RegExpSupport/testData/psi/test3.regexp b/RegExpSupport/testData/psi/test3.regexp
new file mode 100644 (file)
index 0000000..0134ceb
--- /dev/null
@@ -0,0 +1 @@
+(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*
\ No newline at end of file
diff --git a/RegExpSupport/testData/psi/test4.regexp b/RegExpSupport/testData/psi/test4.regexp
new file mode 100644 (file)
index 0000000..0134ceb
--- /dev/null
@@ -0,0 +1 @@
+(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*
\ No newline at end of file
diff --git a/plugins/IntelliLang/IntelliLang-standalone.ipr b/plugins/IntelliLang/IntelliLang-standalone.ipr
new file mode 100644 (file)
index 0000000..1839bd4
--- /dev/null
@@ -0,0 +1,760 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project relativePaths="true" version="4">
+  <component name="AntConfiguration">
+    <defaultAnt bundledAnt="true" />
+    <buildFile url="file://$PROJECT_DIR$/build.xml">
+      <additionalClassPath />
+      <antReference projectDefault="true" />
+      <customJdkName value="" />
+      <maximumHeapSize value="128" />
+      <properties />
+    </buildFile>
+  </component>
+  <component name="BuildJarProjectSettings">
+    <option name="BUILD_JARS_ON_MAKE" value="false" />
+  </component>
+  <component name="CodeStyleProjectProfileManger">
+    <option name="PROJECT_PROFILE" />
+    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+  </component>
+  <component name="CodeStyleSettingsManager">
+    <option name="PER_PROJECT_SETTINGS">
+      <value>
+        <option name="USE_SAME_INDENTS" value="false" />
+        <option name="XML_INDENT_OPTIONS">
+          <value>
+            <option name="INDENT_SIZE" value="2" />
+            <option name="CONTINUATION_INDENT_SIZE" value="4" />
+            <option name="TAB_SIZE" value="8" />
+            <option name="USE_TAB_CHARACTER" value="false" />
+            <option name="SMART_TABS" value="false" />
+            <option name="LABEL_INDENT_SIZE" value="0" />
+            <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+          </value>
+        </option>
+        <option name="OTHER_INDENT_OPTIONS">
+          <value>
+            <option name="INDENT_SIZE" value="2" />
+            <option name="CONTINUATION_INDENT_SIZE" value="8" />
+            <option name="TAB_SIZE" value="8" />
+            <option name="USE_TAB_CHARACTER" value="false" />
+            <option name="SMART_TABS" value="false" />
+            <option name="LABEL_INDENT_SIZE" value="0" />
+            <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+          </value>
+        </option>
+        <option name="CLASS_BRACE_STYLE" value="5" />
+        <option name="METHOD_BRACE_STYLE" value="5" />
+        <option name="SPACE_AFTER_TYPE_CAST" value="false" />
+        <option name="FIELD_NAME_PREFIX" value="my" />
+        <option name="GENERATE_FINAL_LOCALS" value="true" />
+        <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="12" />
+        <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+          <value>
+            <package name="javax.swing" withSubpackages="false" />
+          </value>
+        </option>
+        <option name="IMPORT_LAYOUT_TABLE">
+          <value>
+            <package name="" withSubpackages="true" />
+            <emptyLine />
+            <package name="javax" withSubpackages="true" />
+            <package name="java" withSubpackages="true" />
+            <emptyLine />
+            <package name="org.intellij.plugins" withSubpackages="true" />
+          </value>
+        </option>
+        <option name="IF_BRACE_FORCE" value="1" />
+        <option name="FOR_BRACE_FORCE" value="1" />
+        <ADDITIONAL_INDENT_OPTIONS fileType="java">
+          <option name="INDENT_SIZE" value="4" />
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />
+          <option name="TAB_SIZE" value="4" />
+          <option name="USE_TAB_CHARACTER" value="false" />
+          <option name="SMART_TABS" value="false" />
+          <option name="LABEL_INDENT_SIZE" value="0" />
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+        </ADDITIONAL_INDENT_OPTIONS>
+        <ADDITIONAL_INDENT_OPTIONS fileType="js">
+          <option name="INDENT_SIZE" value="4" />
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />
+          <option name="TAB_SIZE" value="4" />
+          <option name="USE_TAB_CHARACTER" value="false" />
+          <option name="SMART_TABS" value="false" />
+          <option name="LABEL_INDENT_SIZE" value="0" />
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+        </ADDITIONAL_INDENT_OPTIONS>
+        <ADDITIONAL_INDENT_OPTIONS fileType="jsp">
+          <option name="INDENT_SIZE" value="4" />
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />
+          <option name="TAB_SIZE" value="4" />
+          <option name="USE_TAB_CHARACTER" value="false" />
+          <option name="SMART_TABS" value="false" />
+          <option name="LABEL_INDENT_SIZE" value="0" />
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+        </ADDITIONAL_INDENT_OPTIONS>
+        <ADDITIONAL_INDENT_OPTIONS fileType="xml">
+          <option name="INDENT_SIZE" value="2" />
+          <option name="CONTINUATION_INDENT_SIZE" value="4" />
+          <option name="TAB_SIZE" value="8" />
+          <option name="USE_TAB_CHARACTER" value="false" />
+          <option name="SMART_TABS" value="false" />
+          <option name="LABEL_INDENT_SIZE" value="0" />
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+        </ADDITIONAL_INDENT_OPTIONS>
+      </value>
+    </option>
+    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+  </component>
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <option name="DEPLOY_AFTER_MAKE" value="0" />
+    <resourceExtensions>
+      <entry name=".+\.(properties|xml|html|dtd|tld)" />
+      <entry name=".+\.(gif|png|jpeg|jpg)" />
+    </resourceExtensions>
+    <wildcardResourcePatterns>
+      <entry name="?*.properties" />
+      <entry name="?*.xml" />
+      <entry name="?*.gif" />
+      <entry name="?*.png" />
+      <entry name="?*.jpeg" />
+      <entry name="?*.jpg" />
+      <entry name="?*.html" />
+      <entry name="?*.dtd" />
+      <entry name="?*.tld" />
+    </wildcardResourcePatterns>
+  </component>
+  <component name="DependenciesAnalyzeManager">
+    <option name="myForwardDirection" value="false" />
+  </component>
+  <component name="DependencyValidationManager">
+    <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+  </component>
+  <component name="EclipseCompilerSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="true" />
+    <option name="DEPRECATION" value="false" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="EclipseEmbeddedCompilerSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="true" />
+    <option name="DEPRECATION" value="false" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+  <component name="EntryPointsManager">
+    <entry_points version="2.0">
+      <entry_point TYPE="method" FQNAME="org.intellij.