From e9a145669374d74a961b6deac1a307225b454203 Mon Sep 17 00:00:00 2001 From: Dmitrii Rubtsov Date: Sat, 6 May 2023 17:14:21 +0300 Subject: [PATCH] Support for CSS --- README.md | 1 + language-css/.gitignore | 1 + language-css/build.gradle | 46 + .../ui/language/css/CssLanguage.kt | 46 + .../ui/language/css/lexer/CssLexer.java | 1325 +++++++++++++++++ .../ui/language/css/lexer/CssToken.kt | 59 + .../ui/language/css/lexer/css.flex | 132 ++ .../ui/language/css/parser/CssParser.kt | 39 + .../ui/language/css/provider/CssProvider.kt | 58 + .../ui/language/css/styler/CssStyler.kt | 136 ++ 10 files changed, 1843 insertions(+) create mode 100644 language-css/.gitignore create mode 100644 language-css/build.gradle create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/CssLanguage.kt create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssLexer.java create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssToken.kt create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/css.flex create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/parser/CssParser.kt create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/provider/CssProvider.kt create mode 100644 language-css/src/main/kotlin/com/blacksquircle/ui/language/css/styler/CssStyler.kt diff --git a/README.md b/README.md index 573b1e0..66af553 100644 --- a/README.md +++ b/README.md @@ -538,6 +538,7 @@ dependencies { implementation 'com.blacksquircle.ui:language-c:2.6.0' implementation 'com.blacksquircle.ui:language-cpp:2.6.0' implementation 'com.blacksquircle.ui:language-csharp:2.6.0' + implementation 'com.blacksquircle.ui:language-css:2.6.0' implementation 'com.blacksquircle.ui:language-groovy:2.6.0' implementation 'com.blacksquircle.ui:language-html:2.6.0' implementation 'com.blacksquircle.ui:language-java:2.6.0' diff --git a/language-css/.gitignore b/language-css/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/language-css/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/language-css/build.gradle b/language-css/build.gradle new file mode 100644 index 0000000..4ded511 --- /dev/null +++ b/language-css/build.gradle @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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. + */ + +plugins { + id 'java-library' + id 'kotlin' +} + +ext.libraryGroupId = "com.blacksquircle.ui" +ext.libraryArtifactId = "language-css" + +apply from: rootProject.file("gradle/publish.gradle") + +group libraryGroupId +version versions.publishVersionName + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin' +} + +dependencies { + + // Core + implementation library.kotlin + + // Modules + api project(':editorkit:language-base') +} \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/CssLanguage.kt b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/CssLanguage.kt new file mode 100644 index 0000000..94c6d30 --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/CssLanguage.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css + +import com.blacksquircle.ui.language.base.Language +import com.blacksquircle.ui.language.base.parser.LanguageParser +import com.blacksquircle.ui.language.base.provider.SuggestionProvider +import com.blacksquircle.ui.language.base.styler.LanguageStyler +import com.blacksquircle.ui.language.css.parser.CssParser +import com.blacksquircle.ui.language.css.provider.CssProvider +import com.blacksquircle.ui.language.css.styler.CssStyler + +class CssLanguage : Language { + + companion object { + const val LANGUAGE_NAME = "css" + } + + override val languageName = LANGUAGE_NAME + + override fun getParser(): LanguageParser { + return CssParser.getInstance() + } + + override fun getProvider(): SuggestionProvider { + return CssProvider.getInstance() + } + + override fun getStyler(): LanguageStyler { + return CssStyler.getInstance() + } +} \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssLexer.java b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssLexer.java new file mode 100644 index 0000000..4ad13ef --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssLexer.java @@ -0,0 +1,1325 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css.lexer; + +import org.jetbrains.annotations.NotNull; + +@SuppressWarnings("all") + +/** + * This class is a scanner generated by + * JFlex 1.8.2 + * from the specification file css.flex + */ +public class CssLexer { + + /** This character denotes the end of file. */ + public static final int YYEOF = -1; + + /** Initial size of the lookahead buffer. */ + private static final int ZZ_BUFFERSIZE = 16384; + + // Lexical states. + public static final int YYINITIAL = 0; + public static final int CSS_PROPERTY = 2; + public static final int CSS_VALUE = 4; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2 + }; + + /** + * Top-level table for translating characters to character classes + */ + private static final int [] ZZ_CMAP_TOP = zzUnpackcmap_top(); + + private static final String ZZ_CMAP_TOP_PACKED_0 = + "\1\0\1\u0100\1\u0200\1\u0300\1\u0400\1\u0500\1\u0600\1\u0700"+ + "\1\u0800\1\u0900\1\u0a00\1\u0b00\1\u0c00\1\u0d00\1\u0e00\1\u0f00"+ + "\1\u1000\1\u0100\1\u1100\1\u1200\1\u1300\1\u0100\1\u1400\1\u1500"+ + "\1\u1600\1\u1700\1\u1800\1\u1900\1\u1a00\1\u1b00\1\u0100\1\u1c00"+ + "\1\u1d00\1\u1e00\2\u1f00\1\u2000\7\u1f00\1\u2100\1\u2200\1\u2300"+ + "\1\u1f00\1\u2400\1\u2500\2\u1f00\31\u0100\1\u2600\121\u0100\1\u2700"+ + "\4\u0100\1\u2800\1\u0100\1\u2900\1\u2a00\1\u2b00\1\u2c00\1\u2d00"+ + "\1\u2e00\53\u0100\1\u2f00\10\u3000\31\u1f00\1\u0100\1\u3100\1\u3200"+ + "\1\u0100\1\u3300\1\u3400\1\u3500\1\u3600\1\u3700\1\u3800\1\u3900"+ + "\1\u3a00\1\u3b00\1\u0100\1\u3c00\1\u3d00\1\u3e00\1\u3f00\1\u4000"+ + "\1\u4100\1\u4200\1\u4300\1\u4400\1\u4500\1\u4600\1\u4700\1\u4800"+ + "\1\u4900\1\u4a00\1\u4b00\1\u4c00\1\u4d00\1\u4e00\1\u4f00\1\u1f00"+ + "\1\u5000\1\u5100\1\u5200\1\u5300\3\u0100\1\u5400\1\u5500\1\u5600"+ + "\12\u1f00\4\u0100\1\u5700\17\u1f00\2\u0100\1\u5800\41\u1f00\2\u0100"+ + "\1\u5900\1\u5a00\2\u1f00\1\u5b00\1\u5c00\27\u0100\1\u5d00\2\u0100"+ + "\1\u5e00\1\u5f00\1\u6000\1\u6100\42\u1f00\1\u0100\1\u6200\1\u6300"+ + "\11\u1f00\1\u6400\24\u1f00\1\u6500\1\u6600\1\u1f00\1\u6700\1\u6800"+ + "\1\u6900\1\u6a00\2\u1f00\1\u6b00\5\u1f00\1\u6c00\1\u6d00\1\u6e00"+ + "\5\u1f00\1\u6f00\1\u7000\2\u1f00\1\u7100\1\u1f00\1\u7200\2\u1f00"+ + "\1\u7300\11\u1f00\1\u7400\4\u1f00\246\u0100\1\u7500\20\u0100\1\u7600"+ + "\1\u7700\25\u0100\1\u7800\34\u0100\1\u7900\14\u1f00\2\u0100\1\u7a00"+ + "\5\u1f00\23\u5f00\1\u7b00\u0aec\u1f00\1\u7c00\1\u7d00\u02fe\u1f00"; + + private static int [] zzUnpackcmap_top() { + int [] result = new int[4352]; + int offset = 0; + offset = zzUnpackcmap_top(ZZ_CMAP_TOP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackcmap_top(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; + } + + + /** + * Second-level tables for translating characters to character classes + */ + private static final int [] ZZ_CMAP_BLOCKS = zzUnpackcmap_blocks(); + + private static final String ZZ_CMAP_BLOCKS_PACKED_0 = + "\11\0\1\1\1\2\1\3\1\4\1\5\16\0\4\6"+ + "\1\1\1\7\1\10\1\11\1\12\1\13\1\6\1\14"+ + "\1\15\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ + "\12\25\1\26\1\27\1\6\1\30\1\31\1\6\1\32"+ + "\6\33\24\34\1\35\1\36\1\37\1\40\1\34\1\6"+ + "\1\41\1\42\1\43\1\44\1\45\1\46\1\47\1\50"+ + "\1\51\1\34\1\52\1\53\1\54\1\55\1\56\1\57"+ + "\1\34\1\60\1\61\1\62\1\63\1\64\1\65\1\66"+ + "\1\67\1\34\1\70\1\71\1\72\1\73\6\0\1\74"+ + "\32\0\2\6\4\75\4\6\1\76\2\6\1\0\7\6"+ + "\1\76\4\6\1\76\5\6\27\76\1\6\37\76\1\6"+ + "\u01ca\76\4\6\14\76\16\6\5\76\7\6\1\76\1\6"+ + "\1\76\21\6\160\77\5\76\1\6\2\76\2\6\4\76"+ + "\1\6\1\76\6\6\1\76\1\6\3\76\1\6\1\76"+ + "\1\6\24\76\1\6\123\76\1\6\213\76\1\6\5\77"+ + "\2\100\246\76\1\6\46\76\2\6\1\76\6\6\51\76"+ + "\6\6\1\75\1\6\55\77\1\6\1\77\1\6\2\77"+ + "\1\6\2\77\1\6\1\77\10\6\33\76\4\6\4\76"+ + "\15\6\6\0\5\6\1\75\4\6\13\77\1\6\1\0"+ + "\3\6\53\76\37\77\4\6\2\76\1\77\143\76\1\6"+ + "\1\76\7\77\1\0\1\6\6\77\2\76\2\77\1\6"+ + "\4\77\2\76\12\77\3\76\2\6\1\76\17\6\1\0"+ + "\1\76\1\77\36\76\33\77\2\6\131\76\13\77\1\76"+ + "\16\6\12\77\41\76\11\77\2\76\4\6\1\76\2\6"+ + "\1\77\2\75\26\76\4\77\1\76\11\77\1\76\3\77"+ + "\1\76\5\77\22\6\31\76\3\77\4\6\13\76\65\6"+ + "\25\76\1\6\10\76\12\75\13\6\17\77\1\0\41\77"+ + "\66\76\3\77\1\76\22\77\1\76\7\77\12\76\2\77"+ + "\2\6\12\77\1\6\20\76\3\77\1\6\10\76\2\6"+ + "\2\76\2\6\26\76\1\6\7\76\1\6\1\76\3\6"+ + "\4\76\2\6\1\77\1\76\7\77\2\6\2\77\2\6"+ + "\3\77\1\76\10\6\1\77\4\6\2\76\1\6\3\76"+ + "\2\77\2\6\12\77\2\76\2\75\7\6\1\75\1\76"+ + "\1\6\1\77\2\6\3\77\1\6\6\76\4\6\2\76"+ + "\2\6\26\76\1\6\7\76\1\6\2\76\1\6\2\76"+ + "\1\6\2\76\2\6\1\77\1\6\5\77\4\6\2\77"+ + "\2\6\3\77\3\6\1\77\7\6\4\76\1\6\1\76"+ + "\7\6\14\77\3\76\1\77\13\6\3\77\1\6\11\76"+ + "\1\6\3\76\1\6\26\76\1\6\7\76\1\6\2\76"+ + "\1\6\5\76\2\6\1\77\1\76\10\77\1\6\3\77"+ + "\1\6\3\77\2\6\1\76\17\6\2\76\2\77\2\6"+ + "\12\77\1\6\1\75\7\6\1\76\6\77\1\6\3\77"+ + "\1\6\10\76\2\6\2\76\2\6\26\76\1\6\7\76"+ + "\1\6\2\76\1\6\5\76\2\6\1\77\1\76\7\77"+ + "\2\6\2\77\2\6\3\77\7\6\1\0\2\77\4\6"+ + "\2\76\1\6\3\76\2\77\2\6\12\77\1\6\1\76"+ + "\20\6\1\77\1\76\1\6\6\76\3\6\3\76\1\6"+ + "\4\76\3\6\2\76\1\6\1\76\1\6\2\76\3\6"+ + "\2\76\3\6\3\76\3\6\14\76\4\6\5\77\3\6"+ + "\3\77\1\6\4\77\2\6\1\76\6\6\1\77\16\6"+ + "\12\77\11\6\1\75\6\6\5\77\10\76\1\6\3\76"+ + "\1\6\27\76\1\6\20\76\3\6\1\76\7\77\1\6"+ + "\3\77\1\6\4\77\7\6\2\77\1\6\3\76\5\6"+ + "\2\76\2\77\2\6\12\77\20\6\1\76\3\77\1\6"+ + "\10\76\1\6\3\76\1\6\27\76\1\6\12\76\1\6"+ + "\5\76\2\6\1\77\1\76\7\77\1\6\3\77\1\6"+ + "\4\77\7\6\2\77\7\6\1\76\1\6\2\76\2\77"+ + "\2\6\12\77\1\6\2\76\15\6\4\77\1\75\10\76"+ + "\1\6\3\76\1\6\51\76\2\77\1\76\7\77\1\6"+ + "\3\77\1\6\4\77\1\76\5\6\3\76\1\77\7\6"+ + "\3\76\2\77\2\6\12\77\12\6\6\76\1\6\1\0"+ + "\2\77\1\6\22\76\3\6\30\76\1\6\11\76\1\6"+ + "\1\76\2\6\7\76\3\6\1\77\4\6\6\77\1\6"+ + "\1\77\1\6\10\77\6\6\12\77\2\6\2\77\15\6"+ + "\60\76\1\77\2\76\7\77\4\6\1\75\7\76\10\77"+ + "\1\6\12\77\47\6\2\76\1\6\1\76\1\6\5\76"+ + "\1\6\30\76\1\6\1\76\1\6\12\76\1\77\2\76"+ + "\11\77\1\76\2\6\5\76\1\6\1\76\1\6\6\77"+ + "\2\6\12\77\2\6\4\76\40\6\1\76\27\6\2\77"+ + "\6\6\12\77\13\6\1\77\1\6\1\77\1\6\1\77"+ + "\4\6\2\77\10\76\1\6\44\76\4\6\24\77\1\6"+ + "\2\77\5\76\13\77\1\6\44\77\11\6\1\77\71\6"+ + "\53\76\24\77\1\76\12\77\6\6\6\76\4\77\4\76"+ + "\3\77\1\76\3\77\2\76\7\77\3\76\4\77\15\76"+ + "\14\77\1\76\17\77\2\6\46\76\1\6\1\76\5\6"+ + "\1\76\2\6\53\76\1\6\115\76\1\6\4\76\2\6"+ + "\7\76\1\6\1\76\1\6\4\76\2\6\51\76\1\6"+ + "\4\76\2\6\41\76\1\6\4\76\2\6\7\76\1\6"+ + "\1\76\1\6\4\76\2\6\17\76\1\6\71\76\1\6"+ + "\4\76\2\6\103\76\2\6\3\77\40\6\20\76\20\6"+ + "\126\76\2\6\6\76\3\6\u016c\76\2\6\21\76\1\6"+ + "\32\76\5\6\113\76\3\6\13\76\7\6\15\76\1\6"+ + "\4\76\3\77\13\6\22\76\3\77\13\6\22\76\2\77"+ + "\14\6\15\76\1\6\3\76\1\6\2\77\14\6\64\76"+ + "\40\77\3\6\1\76\3\6\1\75\1\76\1\77\2\6"+ + "\12\77\41\6\3\77\1\0\1\6\12\77\6\6\131\76"+ + "\7\6\5\76\2\77\42\76\1\77\1\76\5\6\106\76"+ + "\12\6\37\76\1\6\14\77\4\6\14\77\12\6\12\77"+ + "\36\76\2\6\5\76\13\6\54\76\4\6\32\76\6\6"+ + "\12\77\46\6\27\76\5\77\4\6\65\76\12\77\1\6"+ + "\35\77\2\6\13\77\6\6\12\77\15\6\1\76\10\6"+ + "\16\77\1\100\2\0\77\6\5\77\57\76\21\77\7\76"+ + "\4\6\12\77\21\6\11\77\14\6\3\77\36\76\15\77"+ + "\2\76\12\77\54\76\16\77\14\6\44\76\24\77\10\6"+ + "\12\77\3\6\3\76\12\77\44\76\2\6\11\76\7\6"+ + "\53\76\2\6\3\76\20\6\3\77\1\6\25\77\4\76"+ + "\1\77\6\76\1\77\2\76\3\77\1\76\5\6\300\76"+ + "\72\77\1\6\5\77\26\76\2\6\6\76\2\6\46\76"+ + "\2\6\6\76\2\6\10\76\1\6\1\76\1\6\1\76"+ + "\1\6\1\76\1\6\37\76\2\6\65\76\1\6\7\76"+ + "\1\6\1\76\3\6\3\76\1\6\7\76\3\6\4\76"+ + "\2\6\6\76\4\6\15\76\5\6\3\76\1\6\7\76"+ + "\16\6\5\0\30\6\2\3\5\0\20\6\2\76\23\6"+ + "\1\76\13\6\5\0\1\6\12\0\1\6\1\76\15\6"+ + "\1\76\20\6\15\76\3\6\40\75\20\6\15\77\4\100"+ + "\1\77\3\100\14\77\21\6\1\76\4\6\1\76\2\6"+ + "\12\76\1\6\1\76\3\6\5\76\6\6\1\76\1\6"+ + "\1\76\1\6\1\76\1\6\4\76\1\6\13\76\2\6"+ + "\4\76\5\6\5\76\4\6\1\76\21\6\51\76\u022d\6"+ + "\64\100\26\6\57\76\1\6\57\76\1\6\205\76\6\6"+ + "\4\76\3\77\2\76\14\6\46\76\1\6\1\76\5\6"+ + "\1\76\2\6\70\76\7\6\1\76\17\6\1\77\27\76"+ + "\11\6\7\76\1\6\7\76\1\6\7\76\1\6\7\76"+ + "\1\6\7\76\1\6\7\76\1\6\7\76\1\6\7\76"+ + "\1\6\40\77\57\6\1\76\325\6\3\76\31\6\11\76"+ + "\6\77\1\6\5\76\2\6\5\76\4\6\126\76\2\6"+ + "\2\77\2\6\3\76\1\6\132\76\1\6\4\76\5\6"+ + "\53\76\1\6\136\76\21\6\33\76\5\75\60\6\306\76"+ + "\12\75\100\6\360\76\15\75\3\6\215\76\103\6\56\76"+ + "\2\6\15\76\3\6\20\76\12\77\2\76\24\6\57\76"+ + "\1\77\3\100\1\6\12\77\1\6\37\76\2\77\120\76"+ + "\2\77\45\6\11\76\2\6\147\76\2\6\65\76\2\6"+ + "\5\76\4\75\52\6\2\75\13\76\1\77\3\76\1\77"+ + "\4\76\1\77\27\76\5\77\4\6\1\0\13\6\1\75"+ + "\7\6\64\76\14\6\2\77\62\76\22\77\12\6\12\77"+ + "\6\6\22\77\6\76\3\6\1\76\1\6\2\76\13\77"+ + "\34\76\10\77\2\6\27\76\15\77\14\6\35\76\3\6"+ + "\4\77\57\76\16\77\16\6\1\76\12\77\6\6\5\76"+ + "\1\77\12\76\12\77\5\76\1\6\51\76\16\77\11\6"+ + "\3\76\1\77\10\76\2\77\2\6\12\77\6\6\27\76"+ + "\3\6\1\76\3\77\62\76\1\77\1\76\3\77\2\76"+ + "\2\77\5\76\2\77\1\76\1\77\1\76\30\6\3\76"+ + "\2\6\13\76\5\77\2\6\3\76\2\77\12\6\6\76"+ + "\2\6\6\76\2\6\6\76\11\6\7\76\1\6\7\76"+ + "\1\6\53\76\1\6\14\76\2\75\6\6\163\76\10\77"+ + "\1\6\2\77\2\6\12\77\6\6\244\76\14\6\27\76"+ + "\4\6\61\76\4\6\u0100\3\156\76\2\6\152\76\46\6"+ + "\7\76\14\6\5\76\5\6\1\76\1\77\12\76\1\6"+ + "\15\76\1\6\5\76\1\6\1\76\1\6\2\76\1\6"+ + "\2\76\1\6\154\76\41\6\153\76\22\6\100\76\2\6"+ + "\66\76\50\6\14\76\1\75\3\6\20\77\20\6\20\77"+ + "\3\6\2\76\30\6\3\76\31\6\1\75\6\6\5\76"+ + "\1\6\207\76\2\6\1\0\4\6\1\75\13\6\12\77"+ + "\7\6\32\76\4\6\1\76\1\6\32\76\13\6\131\76"+ + "\3\6\6\76\2\6\6\76\2\6\6\76\2\6\3\76"+ + "\3\6\2\75\3\6\2\75\22\6\3\0\4\6\14\76"+ + "\1\6\32\76\1\6\23\76\1\6\2\76\1\6\17\76"+ + "\2\6\16\76\42\6\173\76\105\6\65\76\210\6\1\77"+ + "\202\6\35\76\3\6\61\76\17\6\1\77\37\6\40\76"+ + "\15\6\36\76\5\6\46\76\5\77\5\6\36\76\2\6"+ + "\44\76\4\6\10\76\1\6\5\76\52\6\236\76\2\6"+ + "\12\77\6\6\44\76\4\6\44\76\4\6\50\76\10\6"+ + "\64\76\234\6\67\76\11\6\26\76\12\6\10\76\230\6"+ + "\6\76\2\6\1\76\1\6\54\76\1\6\2\76\3\6"+ + "\1\76\2\6\27\76\12\6\27\76\11\6\37\76\101\6"+ + "\23\76\1\6\2\76\12\6\26\76\12\6\32\76\106\6"+ + "\70\76\6\6\2\76\100\6\1\76\3\77\1\6\2\77"+ + "\5\6\4\77\4\76\1\6\3\76\1\6\35\76\2\6"+ + "\3\77\4\6\1\77\40\6\35\76\3\6\35\76\43\6"+ + "\10\76\1\6\34\76\2\77\31\6\66\76\12\6\26\76"+ + "\12\6\23\76\15\6\22\76\156\6\111\76\67\6\63\76"+ + "\15\6\63\76\15\6\44\76\4\77\10\6\12\77\u0146\6"+ + "\52\75\1\6\2\0\3\6\2\75\116\6\35\76\12\6"+ + "\1\76\10\6\26\76\13\77\137\6\25\75\33\6\27\76"+ + "\11\6\3\77\65\76\17\77\37\6\12\77\17\6\4\77"+ + "\55\76\13\77\2\6\1\0\17\6\1\0\2\6\31\76"+ + "\7\6\12\77\6\6\3\77\44\76\16\77\1\6\12\77"+ + "\4\6\1\76\2\77\1\75\10\6\43\76\1\77\2\6"+ + "\1\76\11\6\3\77\60\76\16\77\4\76\4\6\4\77"+ + "\1\6\2\0\12\77\1\76\1\6\1\76\43\6\22\76"+ + "\1\6\31\76\14\77\6\6\1\77\101\6\7\76\1\6"+ + "\1\76\1\6\4\76\1\6\17\76\1\6\12\76\7\6"+ + "\57\76\14\77\5\6\12\77\6\6\4\77\1\6\10\76"+ + "\2\6\2\76\2\6\26\76\1\6\7\76\1\6\2\76"+ + "\1\6\5\76\1\6\2\77\1\76\7\77\2\6\2\77"+ + "\2\6\3\77\2\6\1\76\6\6\1\77\5\6\5\76"+ + "\2\77\2\6\7\77\3\6\5\77\213\6\65\76\22\77"+ + "\4\76\5\6\12\77\4\6\1\77\1\76\2\75\36\6"+ + "\60\76\24\77\2\76\1\6\1\76\10\6\12\77\246\6"+ + "\57\76\7\77\2\6\11\77\27\6\4\76\2\77\42\6"+ + "\60\76\21\77\3\6\1\76\13\6\12\77\46\6\53\76"+ + "\15\77\1\76\7\6\12\77\66\6\33\76\2\6\17\77"+ + "\4\6\12\77\306\6\54\76\17\77\145\6\100\76\12\77"+ + "\25\6\1\76\7\75\2\6\1\75\2\6\10\75\1\6"+ + "\2\75\1\6\30\75\6\0\1\6\2\0\2\6\4\0"+ + "\1\75\1\0\1\75\2\0\14\6\12\0\106\6\10\76"+ + "\2\6\47\76\7\77\2\6\7\77\1\76\1\6\1\76"+ + "\1\77\33\6\1\76\12\77\50\76\7\77\1\76\4\77"+ + "\10\6\1\77\10\6\1\76\13\77\56\76\20\77\3\6"+ + "\1\76\42\6\71\76\7\6\11\76\1\6\45\76\10\77"+ + "\1\6\10\77\1\76\17\6\12\77\30\6\36\76\2\6"+ + "\26\77\1\6\16\77\111\6\7\76\1\6\2\76\1\6"+ + "\46\76\6\77\3\6\1\77\1\6\2\77\1\6\7\77"+ + "\1\76\1\77\10\6\12\77\6\6\6\76\1\6\2\76"+ + "\1\6\40\76\5\77\1\6\2\77\1\6\5\77\1\76"+ + "\7\6\12\77\u0136\6\23\76\4\77\271\6\1\75\54\6"+ + "\4\75\37\6\232\76\146\6\157\76\21\6\304\76\274\6"+ + "\57\76\1\6\11\0\307\6\107\76\271\6\71\76\7\6"+ + "\37\76\1\6\12\77\146\6\36\76\2\6\5\77\13\6"+ + "\60\76\7\77\11\6\4\76\14\6\12\77\11\6\25\76"+ + "\5\6\23\76\260\6\100\76\200\6\113\76\4\6\1\77"+ + "\1\76\67\77\7\6\4\77\15\76\100\6\2\76\1\6"+ + "\1\76\1\0\13\6\2\0\16\6\370\76\10\6\363\76"+ + "\u01e3\75\52\6\11\75\367\6\37\76\61\6\3\76\21\6"+ + "\4\76\10\6\u018c\76\4\6\153\76\5\6\15\76\3\6"+ + "\11\76\7\6\12\76\3\6\2\77\1\6\4\0\301\6"+ + "\5\77\3\6\6\77\10\0\10\77\2\6\7\77\36\6"+ + "\4\77\224\6\3\77\273\6\125\76\1\6\107\76\1\6"+ + "\2\76\2\6\1\76\2\6\2\76\2\6\4\76\1\6"+ + "\14\76\1\6\1\76\1\6\7\76\1\6\101\76\1\6"+ + "\4\76\2\6\10\76\1\6\7\76\1\6\34\76\1\6"+ + "\4\76\1\6\5\76\1\6\1\76\3\6\7\76\1\6"+ + "\u0154\76\2\6\31\76\1\6\31\76\1\6\37\76\1\6"+ + "\31\76\1\6\37\76\1\6\31\76\1\6\37\76\1\6"+ + "\31\76\1\6\37\76\1\6\31\76\1\6\10\76\2\6"+ + "\151\77\4\6\62\77\10\6\1\77\16\6\1\77\26\6"+ + "\5\77\1\6\17\77\120\6\7\77\1\6\21\77\2\6"+ + "\7\77\1\6\2\77\1\6\5\77\325\6\55\76\3\6"+ + "\7\77\7\76\2\6\12\77\4\6\1\76\u0171\6\54\76"+ + "\16\77\5\6\1\75\305\76\13\6\7\77\51\6\104\76"+ + "\7\77\1\76\4\6\12\77\u0156\6\1\75\117\6\4\76"+ + "\1\6\33\76\1\6\2\76\1\6\1\76\2\6\1\76"+ + "\1\6\12\76\1\6\4\76\1\6\1\76\1\6\1\76"+ + "\6\6\1\76\4\6\1\76\1\6\1\76\1\6\1\76"+ + "\1\6\3\76\1\6\2\76\1\6\1\76\2\6\1\76"+ + "\1\6\1\76\1\6\1\76\1\6\1\76\1\6\1\76"+ + "\1\6\2\76\1\6\1\76\2\6\4\76\1\6\7\76"+ + "\1\6\4\76\1\6\4\76\1\6\1\76\1\6\12\76"+ + "\1\6\21\76\5\6\3\76\1\6\5\76\1\6\21\76"+ + "\164\6\32\100\6\6\32\100\6\6\32\100\u0166\6\12\0"+ + "\6\6\327\76\7\75\42\6\65\76\13\6\336\76\2\6"+ + "\u0182\76\16\6\u0131\76\37\6\36\76\342\6\113\75\266\6"+ + "\1\0\36\6\140\0\200\6\360\77\20\6"; + + private static int [] zzUnpackcmap_blocks() { + int [] result = new int[32256]; + int offset = 0; + offset = zzUnpackcmap_blocks(ZZ_CMAP_BLOCKS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackcmap_blocks(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 DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\1\1\1\2\2\3\1\4\1\2\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\1\11\1\2\1\14"+ + "\1\15\1\16\1\17\1\20\1\2\1\11\1\21\1\22"+ + "\1\23\1\24\1\25\1\26\1\27\1\30\2\2\1\31"+ + "\1\32\1\31\1\33\1\34\1\2\1\1\1\35\2\1"+ + "\1\14\1\36\1\1\1\4\1\0\1\37\2\14\1\6"+ + "\1\0\1\14\1\40\1\41\1\14\34\0\1\31\1\14"+ + "\2\0\7\1\1\14\2\4\2\6\6\11\1\14\36\0"+ + "\6\31\1\14\1\31\1\0\1\35\1\1\1\11\1\40"+ + "\15\0\1\42\15\0\1\31\24\0\1\43\45\0\1\44"; + + private static int [] zzUnpackAction() { + int [] result = new int[239]; + 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\101\0\202\0\303\0\303\0\u0104\0\u0145\0\u0186"+ + "\0\u01c7\0\u0208\0\303\0\303\0\u0249\0\303\0\303\0\u028a"+ + "\0\u02cb\0\u030c\0\u034d\0\303\0\303\0\303\0\u038e\0\u03cf"+ + "\0\303\0\303\0\303\0\303\0\303\0\303\0\303\0\u01c7"+ + "\0\u0410\0\u0451\0\u0492\0\303\0\u04d3\0\303\0\303\0\u0514"+ + "\0\u0555\0\303\0\u0596\0\u05d7\0\u0618\0\303\0\u0659\0\303"+ + "\0\u069a\0\u06db\0\u0410\0\u071c\0\303\0\u075d\0\u079e\0\u07df"+ + "\0\u0820\0\303\0\u0861\0\u08a2\0\u08e3\0\u0924\0\u0965\0\u09a6"+ + "\0\u09e7\0\u0a28\0\u0a69\0\u0aaa\0\u0aeb\0\u0b2c\0\u0b6d\0\u0bae"+ + "\0\u0bef\0\u0c30\0\u0c71\0\u0cb2\0\u0cf3\0\u0d34\0\u0d75\0\u0db6"+ + "\0\u0df7\0\u0e38\0\u0e79\0\u0eba\0\u0efb\0\u0f3c\0\u0f7d\0\u0fbe"+ + "\0\u0fff\0\u1040\0\u1081\0\u10c2\0\u1103\0\u1144\0\u1185\0\u11c6"+ + "\0\u1207\0\u0659\0\u1248\0\u1289\0\u12ca\0\u130b\0\u134c\0\u138d"+ + "\0\u13ce\0\u140f\0\u1450\0\u1491\0\u0249\0\u14d2\0\u1513\0\u1554"+ + "\0\u1595\0\u15d6\0\u1617\0\u1658\0\u1699\0\u16da\0\u171b\0\u175c"+ + "\0\u179d\0\u17de\0\u181f\0\u1860\0\u18a1\0\u18e2\0\u1923\0\u1964"+ + "\0\u19a5\0\u19e6\0\u1a27\0\u1a68\0\u1aa9\0\u1aea\0\u1b2b\0\u1b6c"+ + "\0\u1bad\0\u1bee\0\u1c2f\0\u1c70\0\u1cb1\0\u1cf2\0\u1d33\0\u1d74"+ + "\0\u1db5\0\u0f7d\0\u0fff\0\u1df6\0\u0820\0\u1e37\0\u1e78\0\303"+ + "\0\u1eb9\0\u1efa\0\u1f3b\0\u1f7c\0\u1fbd\0\u1ffe\0\u203f\0\u2080"+ + "\0\u20c1\0\u2102\0\u2143\0\u2184\0\u21c5\0\303\0\u2206\0\u2247"+ + "\0\u2288\0\u22c9\0\u230a\0\u234b\0\u238c\0\u23cd\0\u240e\0\u244f"+ + "\0\u2490\0\u24d1\0\u2512\0\u2553\0\u2594\0\u25d5\0\u2616\0\u2657"+ + "\0\u2698\0\u26d9\0\u271a\0\u275b\0\u279c\0\u27dd\0\u281e\0\u285f"+ + "\0\u28a0\0\u28e1\0\u2922\0\u2963\0\u29a4\0\u29e5\0\u2a26\0\u2a67"+ + "\0\303\0\u2aa8\0\u2ae9\0\u2b2a\0\u2b6b\0\u2bac\0\u2bed\0\u2c2e"+ + "\0\u2c6f\0\u2cb0\0\u2cf1\0\u2d32\0\u2d73\0\u2db4\0\u2df5\0\u2e36"+ + "\0\u2e77\0\u2eb8\0\u2ef9\0\u2f3a\0\u2f7b\0\u2fbc\0\u2ffd\0\u303e"+ + "\0\u307f\0\u30c0\0\u3101\0\u3142\0\u3183\0\u31c4\0\u3205\0\u3246"+ + "\0\u3287\0\u32c8\0\u3309\0\u334a\0\u338b\0\u33cc\0\303"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[239]; + 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 = + "\1\4\2\5\1\4\1\5\1\6\2\4\1\7\1\10"+ + "\1\11\1\4\1\12\1\13\1\14\1\15\1\16\1\17"+ + "\1\20\1\15\1\21\1\22\1\23\1\24\1\25\1\26"+ + "\1\27\2\30\1\31\1\4\1\32\1\33\27\30\1\34"+ + "\1\35\1\36\1\37\1\4\2\40\3\4\2\5\1\4"+ + "\1\5\1\6\3\4\1\41\1\40\2\4\1\13\1\14"+ + "\1\42\2\4\1\43\1\4\1\21\1\22\1\44\4\4"+ + "\2\45\4\4\27\45\1\46\1\4\1\47\2\4\2\40"+ + "\3\4\2\5\1\4\1\5\1\6\1\4\1\50\1\4"+ + "\1\41\1\51\2\4\1\52\1\14\3\4\1\53\1\4"+ + "\1\54\1\55\1\4\1\56\3\4\2\51\1\4\1\57"+ + "\2\4\27\51\1\4\1\57\1\47\2\4\2\40\2\4"+ + "\103\0\1\5\76\0\2\7\1\0\2\7\1\0\2\7"+ + "\1\60\25\7\1\61\42\7\17\0\1\62\2\0\2\62"+ + "\1\0\1\63\5\0\1\64\1\62\4\0\6\64\21\62"+ + "\11\0\1\40\11\0\1\40\12\0\1\40\5\0\2\40"+ + "\4\0\27\40\4\0\4\40\1\0\2\12\1\0\2\12"+ + "\1\0\6\12\1\65\21\12\1\66\42\12\22\0\2\15"+ + "\1\0\1\15\5\0\2\15\4\0\27\15\33\0\2\15"+ + "\1\0\1\67\5\0\2\15\4\0\27\15\30\0\1\70"+ + "\4\0\1\71\67\0\1\72\7\0\1\22\1\0\1\22"+ + "\15\0\1\73\1\74\1\75\3\0\1\76\2\0\1\77"+ + "\2\0\1\100\1\0\1\72\45\0\1\101\12\0\1\102"+ + "\1\0\1\103\1\104\1\105\1\106\1\0\1\107\2\0"+ + "\1\110\1\0\1\111\1\112\1\0\1\113\1\0\1\114"+ + "\1\0\1\115\57\0\1\116\1\117\1\0\1\120\2\0"+ + "\1\121\1\122\1\0\1\123\1\124\1\0\1\125\4\0"+ + "\1\126\14\0\1\40\11\0\1\40\7\0\2\15\1\0"+ + "\1\30\5\0\2\30\4\0\27\30\4\0\4\40\26\0"+ + "\1\63\5\0\1\63\5\0\6\63\54\0\1\127\10\0"+ + "\2\127\4\0\27\127\33\0\1\127\2\0\1\130\1\131"+ + "\4\0\2\127\4\0\27\127\11\0\1\40\11\0\1\40"+ + "\7\0\1\127\2\0\1\45\1\131\4\0\2\45\4\0"+ + "\27\45\4\0\4\40\52\0\1\132\27\0\1\40\11\0"+ + "\1\51\2\0\1\52\4\0\1\57\1\0\1\57\1\51"+ + "\5\0\2\51\1\0\1\57\2\0\27\51\1\0\1\57"+ + "\2\0\4\40\13\0\1\57\2\0\1\52\4\0\1\57"+ + "\1\0\1\57\1\55\5\0\2\57\1\0\1\57\2\0"+ + "\27\57\1\0\1\57\21\0\1\57\2\0\1\52\1\0"+ + "\1\70\2\0\1\57\1\0\1\133\1\57\5\0\2\57"+ + "\1\0\1\57\2\0\27\57\1\0\1\57\21\0\1\57"+ + "\1\72\1\0\1\52\4\0\1\57\1\22\1\57\1\55"+ + "\5\0\2\57\1\0\1\57\2\0\2\57\1\134\1\135"+ + "\1\136\3\57\1\137\2\57\1\140\2\57\1\141\1\57"+ + "\1\142\6\57\1\0\1\57\21\0\1\57\2\0\1\52"+ + "\4\0\1\57\1\0\2\57\5\0\2\57\1\0\1\57"+ + "\2\0\27\57\1\0\1\57\7\0\1\7\1\143\2\7"+ + "\1\143\1\144\73\7\22\0\2\62\1\0\1\62\5\0"+ + "\2\62\4\0\27\62\33\0\2\62\1\0\1\64\5\0"+ + "\1\64\1\62\4\0\6\64\21\62\11\0\1\12\1\145"+ + "\2\12\1\145\1\146\73\12\13\0\1\72\6\0\1\15"+ + "\1\67\1\0\1\67\5\0\2\15\4\0\2\15\1\147"+ + "\1\150\1\151\3\15\1\152\2\15\1\153\2\15\1\154"+ + "\1\15\1\155\6\15\11\0\17\70\1\156\61\70\2\71"+ + "\4\0\66\71\1\0\4\71\54\0\1\72\71\0\1\157"+ + "\107\0\1\72\11\0\1\72\67\0\1\72\77\0\1\72"+ + "\4\0\1\72\62\0\1\72\16\0\1\72\3\0\1\72"+ + "\53\0\1\160\1\161\3\0\1\162\75\0\1\163\105\0"+ + "\1\164\101\0\1\165\103\0\1\166\1\167\74\0\1\170"+ + "\4\0\1\171\100\0\1\172\63\0\1\173\7\0\1\174"+ + "\105\0\1\175\3\0\1\176\73\0\1\177\101\0\1\200"+ + "\63\0\1\201\110\0\1\202\77\0\1\203\106\0\1\204"+ + "\100\0\1\205\76\0\1\206\71\0\1\207\100\0\1\210"+ + "\74\0\1\211\100\0\1\212\110\0\1\213\51\0\1\127"+ + "\2\0\1\127\1\131\4\0\2\127\4\0\27\127\24\0"+ + "\1\72\6\0\1\127\1\22\1\0\1\130\1\131\4\0"+ + "\2\127\4\0\2\127\1\214\1\215\1\216\3\127\1\217"+ + "\2\127\1\220\2\127\1\221\1\127\1\222\6\127\36\0"+ + "\1\223\5\0\2\223\4\0\27\223\6\0\3\223\54\0"+ + "\1\224\24\0\2\71\4\0\4\71\1\133\2\71\1\225"+ + "\4\71\1\133\1\71\2\133\5\71\2\133\1\71\1\133"+ + "\2\71\27\133\1\71\1\133\2\71\1\0\4\71\12\0"+ + "\1\57\2\0\1\52\4\0\1\57\1\0\2\57\5\0"+ + "\2\57\1\0\1\57\2\0\13\57\1\142\13\57\1\0"+ + "\1\57\21\0\1\57\2\0\1\52\4\0\1\57\1\0"+ + "\2\57\5\0\2\57\1\0\1\57\2\0\4\57\1\226"+ + "\22\57\1\0\1\57\21\0\1\57\2\0\1\52\4\0"+ + "\1\57\1\0\2\57\5\0\2\57\1\0\1\57\2\0"+ + "\13\57\1\142\11\57\1\142\1\57\1\0\1\57\21\0"+ + "\1\57\2\0\1\52\4\0\1\57\1\0\2\57\5\0"+ + "\2\57\1\0\1\57\2\0\14\57\1\142\12\57\1\0"+ + "\1\57\21\0\1\57\2\0\1\52\4\0\1\57\1\0"+ + "\2\57\5\0\2\57\1\0\1\57\2\0\13\57\1\142"+ + "\4\57\1\142\6\57\1\0\1\57\21\0\1\57\2\0"+ + "\1\52\4\0\1\57\1\0\2\57\5\0\2\57\1\0"+ + "\1\57\2\0\2\57\1\142\16\57\1\142\3\57\1\142"+ + "\1\57\1\0\1\57\7\0\1\7\1\143\2\7\1\143"+ + "\1\144\2\7\1\60\25\7\1\61\47\7\1\0\2\7"+ + "\1\60\25\7\1\61\42\7\1\12\1\145\2\12\1\145"+ + "\1\146\6\12\1\65\21\12\1\66\47\12\1\0\6\12"+ + "\1\65\21\12\1\66\42\12\22\0\2\15\1\0\1\15"+ + "\5\0\2\15\4\0\13\15\1\155\13\15\33\0\2\15"+ + "\1\0\1\15\5\0\2\15\4\0\4\15\1\227\22\15"+ + "\33\0\2\15\1\0\1\15\5\0\2\15\4\0\13\15"+ + "\1\155\11\15\1\155\1\15\33\0\2\15\1\0\1\15"+ + "\5\0\2\15\4\0\14\15\1\155\12\15\33\0\2\15"+ + "\1\0\1\15\5\0\2\15\4\0\13\15\1\155\4\15"+ + "\1\155\6\15\33\0\2\15\1\0\1\15\5\0\2\15"+ + "\4\0\2\15\1\155\16\15\1\155\3\15\1\155\1\15"+ + "\11\0\17\70\1\156\4\70\1\230\54\70\47\0\1\72"+ + "\77\0\1\231\77\0\1\232\104\0\1\233\111\0\1\234"+ + "\63\0\1\235\114\0\1\167\76\0\1\236\62\0\1\237"+ + "\117\0\1\240\63\0\1\241\121\0\1\242\71\0\1\243"+ + "\3\0\1\244\74\0\1\245\105\0\1\246\66\0\1\247"+ + "\103\0\1\250\103\0\1\175\102\0\1\251\101\0\1\252"+ + "\60\0\1\253\102\0\1\254\112\0\1\255\102\0\1\256"+ + "\110\0\1\257\55\0\1\260\110\0\1\261\73\0\1\262"+ + "\76\0\1\263\55\0\1\127\2\0\1\127\1\131\4\0"+ + "\2\127\4\0\13\127\1\222\13\127\33\0\1\127\2\0"+ + "\1\127\1\131\4\0\2\127\4\0\4\127\1\264\22\127"+ + "\33\0\1\127\2\0\1\127\1\131\4\0\2\127\4\0"+ + "\13\127\1\222\11\127\1\222\1\127\33\0\1\127\2\0"+ + "\1\127\1\131\4\0\2\127\4\0\14\127\1\222\12\127"+ + "\33\0\1\127\2\0\1\127\1\131\4\0\2\127\4\0"+ + "\13\127\1\222\4\127\1\222\6\127\33\0\1\127\2\0"+ + "\1\127\1\131\4\0\2\127\4\0\2\127\1\222\16\127"+ + "\1\222\3\127\1\222\1\127\70\0\1\265\33\0\1\57"+ + "\2\0\1\52\4\0\1\57\1\0\2\57\5\0\2\57"+ + "\1\0\1\57\2\0\6\57\1\142\20\57\1\0\1\57"+ + "\31\0\2\15\1\0\1\15\5\0\2\15\4\0\6\15"+ + "\1\155\20\15\73\0\1\242\64\0\1\266\112\0\1\267"+ + "\71\0\1\270\72\0\1\271\117\0\1\272\60\0\1\273"+ + "\117\0\1\244\102\0\1\274\62\0\1\275\102\0\1\246"+ + "\113\0\1\276\70\0\1\246\50\0\1\277\145\0\1\276"+ + "\60\0\1\300\102\0\1\301\107\0\1\302\103\0\1\303"+ + "\77\0\1\304\74\0\1\305\70\0\1\306\103\0\1\307"+ + "\74\0\1\310\100\0\1\311\120\0\1\206\35\0\1\127"+ + "\2\0\1\127\1\131\4\0\2\127\4\0\6\127\1\222"+ + "\20\127\67\0\1\312\100\0\1\313\103\0\1\314\103\0"+ + "\1\315\66\0\1\316\115\0\1\246\64\0\1\316\106\0"+ + "\1\246\77\0\1\246\42\0\1\317\121\0\1\320\7\0"+ + "\1\321\2\0\1\322\67\0\1\175\115\0\1\316\77\0"+ + "\1\323\73\0\1\324\46\0\1\325\136\0\1\326\100\0"+ + "\1\327\61\0\1\311\120\0\1\330\77\0\1\331\100\0"+ + "\1\315\102\0\1\332\63\0\1\246\100\0\1\333\76\0"+ + "\1\320\12\0\1\322\72\0\1\334\71\0\1\240\105\0"+ + "\1\335\77\0\1\326\100\0\1\336\101\0\1\337\114\0"+ + "\1\311\57\0\1\340\116\0\1\337\103\0\1\341\40\0"+ + "\1\342\122\0\1\246\105\0\1\343\51\0\1\344\133\0"+ + "\1\326\64\0\1\345\113\0\1\346\65\0\1\347\112\0"+ + "\1\350\100\0\1\333\107\0\1\351\61\0\1\262\102\0"+ + "\1\352\110\0\1\353\70\0\1\354\3\0\1\355\116\0"+ + "\1\356\72\0\1\311\101\0\1\357\100\0\1\231\73\0"+ + "\1\315\102\0\1\315\21\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[13325]; + 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 code for "Unknown internal scanner error". */ + private static final int ZZ_UNKNOWN_ERROR = 0; + /** Error code for "could not match input". */ + private static final int ZZ_NO_MATCH = 1; + /** Error code for "pushback value was too large". */ + private static final int ZZ_PUSHBACK_2BIG = 2; + + /** + * Error messages for {@link #ZZ_UNKNOWN_ERROR}, {@link #ZZ_NO_MATCH}, and + * {@link #ZZ_PUSHBACK_2BIG} respectively. + */ + private static final String ZZ_ERROR_MSG[] = { + "Unknown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state {@code aState} + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\1\2\11\5\1\2\11\1\1\2\11\4\1"+ + "\3\11\2\1\7\11\4\1\1\11\1\1\2\11\2\1"+ + "\1\11\3\1\1\11\1\1\1\11\1\0\3\1\1\11"+ + "\1\0\3\1\1\11\34\0\2\1\2\0\23\1\36\0"+ + "\10\1\1\0\3\1\1\11\15\0\1\11\15\0\1\1"+ + "\24\0\1\11\45\0\1\11"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[239]; + 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; + } + + /** Input device. */ + private java.io.Reader zzReader; + + /** Current state of the DFA. */ + private int zzState; + + /** Current lexical state. */ + private int zzLexicalState = YYINITIAL; + + /** + * This buffer contains the current text to be matched and is the source of the {@link #yytext()} + * string. + */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** Text position at the last accepting state. */ + private int zzMarkedPos; + + /** Current text position in the buffer. */ + private int zzCurrentPos; + + /** Marks the beginning of the {@link #yytext()} string in the buffer. */ + private int zzStartRead; + + /** Marks the last character in the buffer, that has been read from input. */ + private int zzEndRead; + + /** + * Whether the scanner is at the end of file. + * @see #yyatEOF + */ + private boolean zzAtEOF; + + /** + * The number of occupied positions in {@link #zzBuffer} beyond {@link #zzEndRead}. + * + *

When a lead/high surrogate has been read from the input stream into the final + * {@link #zzBuffer} position, this will have a value of 1; otherwise, it will have a value of 0. + */ + private int zzFinalHighSurrogate = 0; + + /** Number of newlines encountered up to the start of the matched text. */ + private int yyline; + + /** Number of characters from the last newline up to the start of the matched text. */ + private int yycolumn; + + /** Number of characters up to the start of the matched text. */ + private long yychar; + + /** Whether the scanner is currently at the beginning of a line. */ + @SuppressWarnings("unused") + private boolean zzAtBOL = true; + + /** Whether the user-EOF-code has already been executed. */ + @SuppressWarnings("unused") + private boolean zzEOFDone; + + /* user code: */ + public final int getTokenStart() { + return (int) yychar; + } + + public final int getTokenEnd() { + return getTokenStart() + yylength(); + } + + + /** + * Creates a new scanner + * + * @param in the java.io.Reader to read input from. + */ + public CssLexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Translates raw input code points to DFA table row + */ + private static int zzCMap(int input) { + int offset = input & 255; + return offset == input ? ZZ_CMAP_BLOCKS[offset] : ZZ_CMAP_BLOCKS[ZZ_CMAP_TOP[input >> 8] | offset]; + } + + /** + * Refills the input buffer. + * + * @return {@code false} iff there was new input. + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead - zzStartRead); + + /* translate stored positions */ + zzEndRead -= zzStartRead; + zzCurrentPos -= zzStartRead; + zzMarkedPos -= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { + /* if not: blow it up */ + char newBuffer[] = new char[zzBuffer.length * 2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + } + + /* fill the buffer with new input */ + int requested = zzBuffer.length - zzEndRead; + int numRead = zzReader.read(zzBuffer, zzEndRead, requested); + + /* not supposed to occur according to specification of java.io.Reader */ + if (numRead == 0) { + throw new java.io.IOException( + "Reader returned 0 characters. See JFlex examples/zero-reader for a workaround."); + } + if (numRead > 0) { + zzEndRead += numRead; + if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { + if (numRead == requested) { // We requested too few chars to encode a full Unicode character + --zzEndRead; + zzFinalHighSurrogate = 1; + } else { // There is room in the buffer for at least one more char + int c = zzReader.read(); // Expecting to read a paired low surrogate char + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char)c; + } + } + } + /* potentially more input available */ + return false; + } + + /* numRead < 0 ==> end of stream */ + return true; + } + + + /** + * Closes the input reader. + * + * @throws java.io.IOException if the reader could not be closed. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; // indicate end of file + zzEndRead = zzStartRead; // invalidate buffer + + if (zzReader != null) { + zzReader.close(); + } + } + + + /** + * Resets the scanner to read from a new input stream. + * + *

Does not close the old reader. + * + *

All internal variables are reset, the old input stream cannot be reused (internal + * buffer is discarded and lost). Lexical state is set to {@code ZZ_INITIAL}. + * + *

Internal scan buffer is resized down to its initial length, if it has grown. + * + * @param reader The new input stream. + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzEOFDone = false; + yyResetPosition(); + zzLexicalState = YYINITIAL; + if (zzBuffer.length > ZZ_BUFFERSIZE) { + zzBuffer = new char[ZZ_BUFFERSIZE]; + } + } + + /** + * Resets the input position. + */ + private final void yyResetPosition() { + zzAtBOL = true; + zzAtEOF = false; + zzCurrentPos = 0; + zzMarkedPos = 0; + zzStartRead = 0; + zzEndRead = 0; + zzFinalHighSurrogate = 0; + yyline = 0; + yycolumn = 0; + yychar = 0L; + } + + + /** + * Returns whether the scanner has reached the end of the reader it reads from. + * + * @return whether the scanner has reached EOF. + */ + public final boolean yyatEOF() { + return zzAtEOF; + } + + + /** + * Returns the current lexical state. + * + * @return 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. + * + * @return the matched text. + */ + public final String yytext() { + return new String(zzBuffer, zzStartRead, zzMarkedPos-zzStartRead); + } + + + /** + * Returns the character at the given position from the matched text. + * + *

It is equivalent to {@code yytext().charAt(pos)}, but faster. + * + * @param position the position of the character to fetch. A value from 0 to {@code yylength()-1}. + * + * @return the character at {@code position}. + */ + public final char yycharat(int position) { + return zzBuffer[zzStartRead + position]; + } + + + /** + * How many characters were matched. + * + * @return the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occurred while scanning. + * + *

In a well-formed scanner (no or only correct usage of {@code 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 error message to display. + */ + private static 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 + * {@link #yylength()}. + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + + + /** + * 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. + */ + @NotNull + public CssToken advance() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char[] zzBufferL = zzBuffer; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + boolean zzR = false; + int zzCh; + int zzCharCount; + for (zzCurrentPosL = zzStartRead ; + zzCurrentPosL < zzMarkedPosL ; + zzCurrentPosL += zzCharCount ) { + zzCh = Character.codePointAt(zzBufferL, zzCurrentPosL, zzMarkedPosL); + zzCharCount = Character.charCount(zzCh); + switch (zzCh) { + case '\u000B': // fall through + case '\u000C': // fall through + case '\u0085': // fall through + case '\u2028': // fall through + case '\u2029': + yyline++; + yycolumn = 0; + zzR = false; + break; + case '\r': + yyline++; + yycolumn = 0; + zzR = true; + break; + case '\n': + if (zzR) + zzR = false; + else { + yyline++; + yycolumn = 0; + } + break; + default: + zzR = false; + yycolumn += zzCharCount; + } + } + + if (zzR) { + // peek one character ahead if it is + // (if we have counted one line too much) + boolean zzPeek; + if (zzMarkedPosL < zzEndReadL) + zzPeek = zzBufferL[zzMarkedPosL] == '\n'; + else if (zzAtEOF) + zzPeek = false; + else { + boolean eof = zzRefill(); + zzEndReadL = zzEndRead; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + if (eof) + zzPeek = false; + else + zzPeek = zzBufferL[zzMarkedPosL] == '\n'; + } + if (zzPeek) yyline--; + } + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + // set up zzAction for empty match case: + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + } + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMap(zzInput) ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return CssToken.EOF; + } + } + else { + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 1: + { return CssToken.VALUE; + } + // fall through + case 37: break; + case 2: + { return CssToken.BAD_CHARACTER; + } + // fall through + case 38: break; + case 3: + { return CssToken.WHITESPACE; + } + // fall through + case 39: break; + case 4: + { return CssToken.DOUBLE_QUOTED_STRING; + } + // fall through + case 40: break; + case 5: + { return CssToken.DOLLAR; + } + // fall through + case 41: break; + case 6: + { return CssToken.SINGLE_QUOTED_STRING; + } + // fall through + case 42: break; + case 7: + { return CssToken.LPAREN; + } + // fall through + case 43: break; + case 8: + { return CssToken.RPAREN; + } + // fall through + case 44: break; + case 9: + { return CssToken.DATA_TYPE; + } + // fall through + case 45: break; + case 10: + { return CssToken.PLUS; + } + // fall through + case 46: break; + case 11: + { return CssToken.COMMA; + } + // fall through + case 47: break; + case 12: + { return CssToken.NUMBER; + } + // fall through + case 48: break; + case 13: + { return CssToken.COLON; + } + // fall through + case 49: break; + case 14: + { return CssToken.SEMICOLON; + } + // fall through + case 50: break; + case 15: + { return CssToken.EQ; + } + // fall through + case 51: break; + case 16: + { return CssToken.GT; + } + // fall through + case 52: break; + case 17: + { return CssToken.LBRACK; + } + // fall through + case 53: break; + case 18: + { return CssToken.RBRACK; + } + // fall through + case 54: break; + case 19: + { return CssToken.XOR; + } + // fall through + case 55: break; + case 20: + { yybegin(CSS_PROPERTY); return CssToken.LBRACE; + } + // fall through + case 56: break; + case 21: + { return CssToken.OR; + } + // fall through + case 57: break; + case 22: + { return CssToken.RBRACE; + } + // fall through + case 58: break; + case 23: + { return CssToken.TILDE; + } + // fall through + case 59: break; + case 24: + { return CssToken.IDENTIFIER; + } + // fall through + case 60: break; + case 25: + { return CssToken.PROPERTY; + } + // fall through + case 61: break; + case 26: + { yybegin(CSS_VALUE); return CssToken.COLON; + } + // fall through + case 62: break; + case 27: + { return CssToken.LBRACE; + } + // fall through + case 63: break; + case 28: + { yybegin(YYINITIAL); return CssToken.RBRACE; + } + // fall through + case 64: break; + case 29: + { return CssToken.FUNCTION; + } + // fall through + case 65: break; + case 30: + { yybegin(CSS_PROPERTY); return CssToken.SEMICOLON; + } + // fall through + case 66: break; + case 31: + { return CssToken.ANNOTATION; + } + // fall through + case 67: break; + case 32: + { return CssToken.BLOCK_COMMENT; + } + // fall through + case 68: break; + case 33: + { return CssToken.LINE_COMMENT; + } + // fall through + case 69: break; + case 34: + { return CssToken.RESERVED_WORD; + } + // fall through + case 70: break; + case 35: + { return CssToken.REGEX; + } + // fall through + case 71: break; + case 36: + { return CssToken.IMPORTANT; + } + // fall through + case 72: break; + default: + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssToken.kt b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssToken.kt new file mode 100644 index 0000000..98ee267 --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/CssToken.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css.lexer + +enum class CssToken { + NUMBER, + DATA_TYPE, + RESERVED_WORD, + REGEX, + ANNOTATION, + IMPORTANT, + + PROPERTY, + VALUE, + FUNCTION, + + PLUS, + GT, + TILDE, + XOR, + DOLLAR, + OR, + EQ, + + LPAREN, + RPAREN, + LBRACE, + RBRACE, + LBRACK, + RBRACK, + COLON, + SEMICOLON, + COMMA, + + DOUBLE_QUOTED_STRING, + SINGLE_QUOTED_STRING, + + LINE_COMMENT, + BLOCK_COMMENT, + + IDENTIFIER, + WHITESPACE, + BAD_CHARACTER, + EOF +} \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/css.flex b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/css.flex new file mode 100644 index 0000000..34704f9 --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/lexer/css.flex @@ -0,0 +1,132 @@ +package com.blacksquircle.ui.language.css.lexer; + +@SuppressWarnings("all") +%% + +%public +%class CssLexer +%type CssToken +%function advance +%unicode +%line +%column +%char + +%{ + public final int getTokenStart() { + return (int) yychar; + } + + public final int getTokenEnd() { + return getTokenStart() + yylength(); + } +%} + +IDENTIFIER = [:jletter:] [:jletterdigit:]* + +DIGIT = ([0-9]) +LETTER = ([A-Za-z]) +LETTER_OR_UNDERSCORE = ({LETTER}|[_]) +LETTER_OR_UNDERSCORE_OR_DASH = ({LETTER_OR_UNDERSCORE}|[\-]) +CSS_DIGITS = ([\-]?{DIGIT}+([0-9\.]+)?(pt|pc|in|mm|cm|em|ex|px|ms|s|deg|%)?) +CSS_HEX = ("#"[0-9a-fA-F]+) +CSS_NUMBER = ({CSS_DIGITS}|{CSS_HEX}) + +CSS_SELECTOR_PIECE = (("*"|"."|{LETTER_OR_UNDERSCORE_OR_DASH})({LETTER_OR_UNDERSCORE_OR_DASH}|"."|{DIGIT})*) +CSS_PSEUDO_CLASS = (":"("root"|"nth-child"|"nth-last-child"|"nth-of-type"|"nth-last-of-type"|"first-child"|"last-child"|"first-of-type"|"last-of-type"|"only-child"|"only-of-type"|"empty"|"link"|"visited"|"active"|"hover"|"focus"|"target"|"lang"|"enabled"|"disabled"|"checked"|":first-line"|":first-letter"|":before"|":after"|"not")) +CSS_AT_RULE = ("@"(charset|import|namespace|media|document|page|font-face|keyframes|viewport)) +CSS_ID = ("#"{CSS_SELECTOR_PIECE}) + +CSS_PROPERTY_RULE = ([\*]?{LETTER_OR_UNDERSCORE_OR_DASH}({LETTER_OR_UNDERSCORE_OR_DASH}|{DIGIT})*(:[\w]+)?) +CSS_VALUE_CHAR = ({LETTER_OR_UNDERSCORE_OR_DASH}|{DIGIT}|[\\/|$]) +CSS_VALUE_RULE = ({CSS_VALUE_CHAR}*) +CSS_FUNCTION = ({CSS_VALUE_RULE}\() + +CRLF = [\ \t \f]* \R +DOUBLE_QUOTED_STRING = \"([^\\\"\r\n] | \\[^\r\n] | \\{CRLF})*\"? +SINGLE_QUOTED_STRING = '([^\\'\r\n] | \\[^\r\n] | \\{CRLF})*'? + +LINE_TERMINATOR = \r|\n|\r\n +WHITESPACE = {LINE_TERMINATOR} | [ \t\f] + +LINE_COMMENT = "//".* +BLOCK_COMMENT = "/"\*([^*] | \*+[^*/])*(\*+"/")? + +%state CSS_PROPERTY +%state CSS_VALUE + +%% + + { + {CSS_NUMBER} { return CssToken.NUMBER; } + {CSS_SELECTOR_PIECE} { return CssToken.DATA_TYPE; } + {CSS_PSEUDO_CLASS} { return CssToken.RESERVED_WORD; } + {CSS_AT_RULE} { return CssToken.REGEX; } + {CSS_ID} { return CssToken.ANNOTATION; } + + "+" { return CssToken.PLUS; } + ">" { return CssToken.GT; } + "~" { return CssToken.TILDE; } + "^" { return CssToken.XOR; } + "$" { return CssToken.DOLLAR; } + "|" { return CssToken.OR; } + "=" { return CssToken.EQ; } + + "(" { return CssToken.LPAREN; } + ")" { return CssToken.RPAREN; } + "{" { yybegin(CSS_PROPERTY); return CssToken.LBRACE; } + "}" { return CssToken.RBRACE; } + "[" { return CssToken.LBRACK; } + "]" { return CssToken.RBRACK; } + ":" { return CssToken.COLON; } + ";" { return CssToken.SEMICOLON; } + "," { return CssToken.COMMA; } + + {LINE_COMMENT} { return CssToken.LINE_COMMENT; } + {BLOCK_COMMENT} { return CssToken.BLOCK_COMMENT; } + + {DOUBLE_QUOTED_STRING} { return CssToken.DOUBLE_QUOTED_STRING; } + {SINGLE_QUOTED_STRING} { return CssToken.SINGLE_QUOTED_STRING; } + + {IDENTIFIER} { return CssToken.IDENTIFIER; } + {WHITESPACE} { return CssToken.WHITESPACE; } +} + + { + {CSS_NUMBER} { return CssToken.NUMBER; } + {CSS_PROPERTY_RULE} { return CssToken.PROPERTY; } + + "(" { return CssToken.LPAREN; } + ")" { return CssToken.RPAREN; } + "{" { return CssToken.LBRACE; } + "}" { yybegin(YYINITIAL); return CssToken.RBRACE; } + ":" { yybegin(CSS_VALUE); return CssToken.COLON; } + + {LINE_COMMENT} { return CssToken.LINE_COMMENT; } + {BLOCK_COMMENT} { return CssToken.BLOCK_COMMENT; } + + {IDENTIFIER} { return CssToken.IDENTIFIER; } + {WHITESPACE} { return CssToken.WHITESPACE; } +} + + { + {CSS_NUMBER} { return CssToken.NUMBER; } + {CSS_VALUE_RULE} { return CssToken.VALUE; } + {CSS_FUNCTION} { return CssToken.FUNCTION; } + + "(" { return CssToken.LPAREN; } + ")" { return CssToken.RPAREN; } + "}" { yybegin(YYINITIAL); return CssToken.RBRACE; } + ";" { yybegin(CSS_PROPERTY); return CssToken.SEMICOLON; } + "!important" { return CssToken.IMPORTANT; } + + {LINE_COMMENT} { return CssToken.LINE_COMMENT; } + {BLOCK_COMMENT} { return CssToken.BLOCK_COMMENT; } + + {IDENTIFIER} { return CssToken.IDENTIFIER; } + {WHITESPACE} { return CssToken.WHITESPACE; } +} + +[^] { return CssToken.BAD_CHARACTER; } + +<> { return CssToken.EOF; } \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/parser/CssParser.kt b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/parser/CssParser.kt new file mode 100644 index 0000000..3c3ea31 --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/parser/CssParser.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css.parser + +import com.blacksquircle.ui.language.base.model.ParseResult +import com.blacksquircle.ui.language.base.model.TextStructure +import com.blacksquircle.ui.language.base.parser.LanguageParser + +class CssParser private constructor() : LanguageParser { + + companion object { + + private var cssParser: CssParser? = null + + fun getInstance(): CssParser { + return cssParser ?: CssParser().also { + cssParser = it + } + } + } + + override fun execute(structure: TextStructure): ParseResult { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/provider/CssProvider.kt b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/provider/CssProvider.kt new file mode 100644 index 0000000..4a5c5b2 --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/provider/CssProvider.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css.provider + +import com.blacksquircle.ui.language.base.model.Suggestion +import com.blacksquircle.ui.language.base.model.TextStructure +import com.blacksquircle.ui.language.base.provider.SuggestionProvider +import com.blacksquircle.ui.language.base.utils.WordsManager + +class CssProvider private constructor() : SuggestionProvider { + + companion object { + + private var cssProvider: CssProvider? = null + + fun getInstance(): CssProvider { + return cssProvider ?: CssProvider().also { + cssProvider = it + } + } + } + + private val wordsManager = WordsManager() + + override fun getAll(): Set { + return wordsManager.getWords() + } + + override fun processAllLines(structure: TextStructure) { + wordsManager.processAllLines(structure) + } + + override fun processLine(lineNumber: Int, text: CharSequence) { + wordsManager.processLine(lineNumber, text) + } + + override fun deleteLine(lineNumber: Int) { + wordsManager.deleteLine(lineNumber) + } + + override fun clearLines() { + wordsManager.clearLines() + } +} \ No newline at end of file diff --git a/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/styler/CssStyler.kt b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/styler/CssStyler.kt new file mode 100644 index 0000000..5535fde --- /dev/null +++ b/language-css/src/main/kotlin/com/blacksquircle/ui/language/css/styler/CssStyler.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2023 Squircle CE contributors. + * + * 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 com.blacksquircle.ui.language.css.styler + +import com.blacksquircle.ui.language.base.model.SyntaxHighlightResult +import com.blacksquircle.ui.language.base.model.TextStructure +import com.blacksquircle.ui.language.base.model.TokenType +import com.blacksquircle.ui.language.base.styler.LanguageStyler +import com.blacksquircle.ui.language.css.lexer.CssLexer +import com.blacksquircle.ui.language.css.lexer.CssToken +import java.io.StringReader + +class CssStyler private constructor() : LanguageStyler { + + companion object { + + private var cssStyler: CssStyler? = null + + fun getInstance(): CssStyler { + return cssStyler ?: CssStyler().also { + cssStyler = it + } + } + } + + override fun execute(structure: TextStructure): List { + val source = structure.text.toString() + val syntaxHighlightResults = mutableListOf() + val sourceReader = StringReader(source) + val lexer = CssLexer(sourceReader) + + while (true) { + try { + when (lexer.advance()) { + CssToken.NUMBER -> { + val tokenType = TokenType.NUMBER + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.PLUS, + CssToken.GT, + CssToken.TILDE, + CssToken.XOR, + CssToken.DOLLAR, + CssToken.OR, + CssToken.EQ, + CssToken.LPAREN, + CssToken.RPAREN, + CssToken.LBRACE, + CssToken.RBRACE, + CssToken.LBRACK, + CssToken.RBRACK, + CssToken.COLON -> { + val tokenType = TokenType.OPERATOR + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.SEMICOLON, + CssToken.COMMA -> { + continue // skip + } + CssToken.DATA_TYPE, + CssToken.RESERVED_WORD -> { + val tokenType = TokenType.TAG_NAME + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.REGEX, + CssToken.ANNOTATION, + CssToken.IMPORTANT -> { + val tokenType = TokenType.ATTR_VALUE + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.PROPERTY -> { + val tokenType = TokenType.ATTR_NAME + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.VALUE -> { + val tokenType = TokenType.ATTR_VALUE + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.FUNCTION -> { + val tokenType = TokenType.KEYWORD + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd - 1) + syntaxHighlightResults.add(syntaxHighlightResult) + + val braceType = TokenType.OPERATOR + val braceResult = SyntaxHighlightResult(braceType, lexer.tokenEnd - 1, lexer.tokenEnd) + syntaxHighlightResults.add(braceResult) + } + CssToken.DOUBLE_QUOTED_STRING, + CssToken.SINGLE_QUOTED_STRING -> { + val tokenType = TokenType.STRING + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.LINE_COMMENT, + CssToken.BLOCK_COMMENT -> { + val tokenType = TokenType.COMMENT + val syntaxHighlightResult = SyntaxHighlightResult(tokenType, lexer.tokenStart, lexer.tokenEnd) + syntaxHighlightResults.add(syntaxHighlightResult) + } + CssToken.IDENTIFIER, + CssToken.WHITESPACE, + CssToken.BAD_CHARACTER -> { + continue + } + CssToken.EOF -> { + break + } + } + } catch (e: Throwable) { + e.printStackTrace() + break + } + } + return syntaxHighlightResults + } +} \ No newline at end of file