--- /dev/null
+<?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) &#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) &#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) &#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="/* * Copyright (c) &#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="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) &#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) &#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) &#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) &#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>
+
--- /dev/null
+<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>
--- /dev/null
+<?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 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." />
+ <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) &#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) &#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="/* * Copyright (c) &#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="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) &#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) &#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) &#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) &#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>
+
--- /dev/null
+<?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) &#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) &#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) &#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="/* * Copyright (c) &#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="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) &#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) &#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) &#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) &#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>
+
--- /dev/null
+<?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) &#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) &#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) &#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="/* * Copyright (c) &#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="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) &#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) &#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) &#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) &#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>
+
--- /dev/null
+<?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
--- /dev/null
+<!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>
--- /dev/null
+/*
+ * 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));
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+ };
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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";
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/* 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);
+ }
+ }
+ }
+ }
+
+
+}
--- /dev/null
+/*
+ * 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 {
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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 {
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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;
+ }
+ };
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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", },
+ };
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/* 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; }
--- /dev/null
+/*
+ * 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 + ")";
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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]");
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+<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&&[cd]]</pattern>
+ <expected>OK</expected>
+ </test>
+ <test>
+ <pattern>a[b-&&[cd]]</pattern>
+ <expected>ERR</expected>
+ </test>
+ <test>
+ <pattern>a[b&&-]</pattern>
+ <expected>OK</expected>
+ </test>
+ <test>
+ <pattern>a[b&&-b]</pattern>
+ <expected jdk="OK">OK</expected>
+ </test>
+ <test>
+ <pattern>[&&]</pattern>
+ <expected>ERR</expected>
+ </test>
+ <test>
+ <pattern>a[b&&c&&d]</pattern>
+ <expected>OK</expected>
+ </test>
+ <test>
+ <pattern>a[b&&c&&d-e&&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}&&[^\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>.*?(<(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>
--- /dev/null
+123 | 456
\ No newline at end of file
--- /dev/null
+1*<error descr="Dangling metacharacter">*</error>
\ No newline at end of file
--- /dev/null
+(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*
\ No newline at end of file
--- /dev/null
+(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*
\ No newline at end of file
--- /dev/null
+<?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.