diff --git a/.idea/misc.xml b/.idea/misc.xml
index 7e6d5e6a9..b0e776b69 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -14,7 +14,7 @@
-
+
diff --git a/.idea/runConfigurations/Plugin.xml b/.idea/runConfigurations/Plugin.xml
index 294c0ddc6..a34209a9e 100644
--- a/.idea/runConfigurations/Plugin.xml
+++ b/.idea/runConfigurations/Plugin.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/JFlex.jar b/JFlex.jar
new file mode 100644
index 000000000..8bef2fdba
Binary files /dev/null and b/JFlex.jar differ
diff --git a/gen/com/simpleplugin/parser/SimpleParser.java b/gen/com/simpleplugin/parser/SimpleParser.java
index 067b2bb80..d8a7495ee 100644
--- a/gen/com/simpleplugin/parser/SimpleParser.java
+++ b/gen/com/simpleplugin/parser/SimpleParser.java
@@ -1,13 +1,11 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.parser;
-import org.jetbrains.annotations.*;
-import com.intellij.lang.LighterASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import com.intellij.openapi.diagnostic.Logger;
import static com.simpleplugin.psi.SimpleTypes.*;
-import static com.simpleplugin.parser.GeneratedParserUtilBase.*;
+import static com.intellij.lang.parser.GeneratedParserUtilBase.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.TokenSet;
@@ -16,24 +14,19 @@ import com.intellij.lang.PsiParser;
@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"})
public class SimpleParser implements PsiParser {
- public static Logger LOG_ = Logger.getInstance("com.simpleplugin.parser.SimpleParser");
+ public static final Logger LOG_ = Logger.getInstance("com.simpleplugin.parser.SimpleParser");
- @NotNull
public ASTNode parse(IElementType root_, PsiBuilder builder_) {
- int level_ = 0;
boolean result_;
- builder_ = adapt_builder_(root_, builder_, this);
+ builder_ = adapt_builder_(root_, builder_, this, null);
+ Marker marker_ = enter_section_(builder_, 0, _COLLAPSE_, null);
if (root_ == PROPERTY) {
- result_ = property(builder_, level_ + 1);
+ result_ = property(builder_, 0);
}
else {
- Marker marker_ = builder_.mark();
- result_ = parse_root_(root_, builder_, level_);
- while (builder_.getTokenType() != null) {
- builder_.advanceLexer();
- }
- marker_.done(root_);
+ result_ = parse_root_(root_, builder_, 0);
}
+ exit_section_(builder_, 0, marker_, root_, result_, true, TRUE_CONDITION);
return builder_.getTreeBuilt();
}
@@ -42,26 +35,15 @@ public class SimpleParser implements PsiParser {
}
/* ********************************************************** */
- // (property|COMMENT|CRLF)
+ // property|COMMENT|CRLF
static boolean item_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "item_")) return false;
- return item__0(builder_, level_ + 1);
- }
-
- // property|COMMENT|CRLF
- private static boolean item__0(PsiBuilder builder_, int level_) {
- if (!recursion_guard_(builder_, level_, "item__0")) return false;
boolean result_ = false;
- Marker marker_ = builder_.mark();
+ Marker marker_ = enter_section_(builder_);
result_ = property(builder_, level_ + 1);
if (!result_) result_ = consumeToken(builder_, COMMENT);
if (!result_) result_ = consumeToken(builder_, CRLF);
- if (!result_) {
- marker_.rollbackTo();
- }
- else {
- marker_.drop();
- }
+ exit_section_(builder_, marker_, null, result_);
return result_;
}
@@ -69,56 +51,37 @@ public class SimpleParser implements PsiParser {
// (KEY? SEPARATOR VALUE?) | KEY
public static boolean property(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "property")) return false;
- if (!nextTokenIs(builder_, KEY) && !nextTokenIs(builder_, SEPARATOR)
- && replaceVariants(builder_, 2, "")) return false;
+ if (!nextTokenIs(builder_, "", KEY, SEPARATOR)) return false;
boolean result_ = false;
- Marker marker_ = builder_.mark();
- enterErrorRecordingSection(builder_, level_, _SECTION_GENERAL_, "");
+ Marker marker_ = enter_section_(builder_, level_, _NONE_, "");
result_ = property_0(builder_, level_ + 1);
if (!result_) result_ = consumeToken(builder_, KEY);
- if (result_) {
- marker_.done(PROPERTY);
- }
- else {
- marker_.rollbackTo();
- }
- result_ = exitErrorRecordingSection(builder_, level_, result_, false, _SECTION_GENERAL_, null);
+ exit_section_(builder_, level_, marker_, PROPERTY, result_, false, null);
return result_;
}
- // (KEY? SEPARATOR VALUE?)
+ // KEY? SEPARATOR VALUE?
private static boolean property_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "property_0")) return false;
- return property_0_0(builder_, level_ + 1);
- }
-
- // KEY? SEPARATOR VALUE?
- private static boolean property_0_0(PsiBuilder builder_, int level_) {
- if (!recursion_guard_(builder_, level_, "property_0_0")) return false;
boolean result_ = false;
- Marker marker_ = builder_.mark();
- result_ = property_0_0_0(builder_, level_ + 1);
+ Marker marker_ = enter_section_(builder_);
+ result_ = property_0_0(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, SEPARATOR);
- result_ = result_ && property_0_0_2(builder_, level_ + 1);
- if (!result_) {
- marker_.rollbackTo();
- }
- else {
- marker_.drop();
- }
+ result_ = result_ && property_0_2(builder_, level_ + 1);
+ exit_section_(builder_, marker_, null, result_);
return result_;
}
// KEY?
- private static boolean property_0_0_0(PsiBuilder builder_, int level_) {
- if (!recursion_guard_(builder_, level_, "property_0_0_0")) return false;
+ private static boolean property_0_0(PsiBuilder builder_, int level_) {
+ if (!recursion_guard_(builder_, level_, "property_0_0")) return false;
consumeToken(builder_, KEY);
return true;
}
// VALUE?
- private static boolean property_0_0_2(PsiBuilder builder_, int level_) {
- if (!recursion_guard_(builder_, level_, "property_0_0_2")) return false;
+ private static boolean property_0_2(PsiBuilder builder_, int level_) {
+ if (!recursion_guard_(builder_, level_, "property_0_2")) return false;
consumeToken(builder_, VALUE);
return true;
}
@@ -127,15 +90,11 @@ public class SimpleParser implements PsiParser {
// item_*
static boolean simpleFile(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "simpleFile")) return false;
- int offset_ = builder_.getCurrentOffset();
+ int pos_ = current_position_(builder_);
while (true) {
if (!item_(builder_, level_ + 1)) break;
- int next_offset_ = builder_.getCurrentOffset();
- if (offset_ == next_offset_) {
- empty_element_parsed_guard_(builder_, offset_, "simpleFile");
- break;
- }
- offset_ = next_offset_;
+ if (!empty_element_parsed_guard_(builder_, "simpleFile", pos_)) break;
+ pos_ = current_position_(builder_);
}
return true;
}
diff --git a/gen/com/simpleplugin/parser/SimpleParserUtil.java b/gen/com/simpleplugin/parser/SimpleParserUtil.java
new file mode 100644
index 000000000..057161c56
--- /dev/null
+++ b/gen/com/simpleplugin/parser/SimpleParserUtil.java
@@ -0,0 +1,6 @@
+package com.simpleplugin.parser;
+
+import com.intellij.lang.parser.GeneratedParserUtilBase;
+
+public class SimpleParserUtil extends GeneratedParserUtilBase {
+}
diff --git a/idea-flex.skeleton b/idea-flex.skeleton
new file mode 100644
index 000000000..234a62c41
--- /dev/null
+++ b/idea-flex.skeleton
@@ -0,0 +1,251 @@
+ /** initial size of the lookahead buffer */
+--- private static final int ZZ_BUFFERSIZE = ...;
+
+ /** lexical states */
+--- lexical states, charmap
+
+ /* 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"
+ };
+
+--- isFinal list
+ /** 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;
+
+--- user class code
+
+--- constructor declaration
+
+ 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);
+ }
+
+ /**
+ * Refills the input buffer.
+ *
+ * @return false
, 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 pos 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
+ */
+--- zzScanError declaration
+ String message;
+ try {
+ message = ZZ_ERROR_MSG[errorCode];
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+ }
+
+--- throws clause
+ }
+
+
+ /**
+ * 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()!
+ */
+--- yypushback decl (contains zzScanError exception)
+ if ( number > yylength() )
+ zzScanError(ZZ_PUSHBACK_2BIG);
+
+ zzMarkedPos -= number;
+ }
+
+
+--- zzDoEOF
+ /**
+ * 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
+ */
+--- yylex declaration
+ int zzInput;
+ int zzAction;
+
+ // cached fields:
+ int zzCurrentPosL;
+ int zzMarkedPosL;
+ int zzEndReadL = zzEndRead;
+ CharSequence zzBufferL = zzBuffer;
+ char[] zzBufferArrayL = zzBufferArray;
+ char [] zzCMapL = ZZ_CMAP;
+
+--- local declarations
+
+ while (true) {
+ zzMarkedPosL = zzMarkedPos;
+
+--- start admin (line, char, col count)
+ zzAction = -1;
+
+ zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+--- start admin (lexstate etc)
+
+ zzForAction: {
+ while (true) {
+
+--- next input, line, col, char count, next transition, isFinal action
+ zzAction = zzState;
+ zzMarkedPosL = zzCurrentPosL;
+--- line count update
+ }
+
+ }
+ }
+
+ // store back cached position
+ zzMarkedPos = zzMarkedPosL;
+--- char count update
+
+--- actions
+ default:
+ if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+ zzAtEOF = true;
+--- eofvalue
+ }
+ else {
+--- no match
+ }
+ }
+ }
+ }
+
+--- main
+
+}
diff --git a/src/com/simpleplugin/Simple.bnf b/src/com/simpleplugin/Simple.bnf
index c46edce67..ed3f443d6 100644
--- a/src/com/simpleplugin/Simple.bnf
+++ b/src/com/simpleplugin/Simple.bnf
@@ -1,6 +1,6 @@
{
parserClass="com.simpleplugin.parser.SimpleParser"
- stubParserClass="com.simpleplugin.parser.GeneratedParserUtilBase"
+ parserUtilClass="com.simpleplugin.parser.SimpleParserUtil"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
diff --git a/src/com/simpleplugin/SimpleFindUsagesProvider.java b/src/com/simpleplugin/SimpleFindUsagesProvider.java
index cb441ddae..b02e4f6c1 100644
--- a/src/com/simpleplugin/SimpleFindUsagesProvider.java
+++ b/src/com/simpleplugin/SimpleFindUsagesProvider.java
@@ -17,7 +17,7 @@ import java.io.Reader;
public class SimpleFindUsagesProvider implements FindUsagesProvider {
private static final DefaultWordsScanner WORDS_SCANNER =
- new DefaultWordsScanner(new FlexAdapter(new SimpleLexer((Reader) null)),
+ new DefaultWordsScanner(new SimpleLexerAdapter(),
TokenSet.create(SimpleTypes.KEY), TokenSet.create(SimpleTypes.COMMENT), TokenSet.EMPTY);
@Nullable
diff --git a/src/com/simpleplugin/SimpleLexer.java b/src/com/simpleplugin/SimpleLexer.java
index 61884cfe2..d03bce1b0 100644
--- a/src/com/simpleplugin/SimpleLexer.java
+++ b/src/com/simpleplugin/SimpleLexer.java
@@ -1,4 +1,4 @@
-/* The following code was generated by JFlex 1.4.3 on 2/19/13 7:59 PM */
+/* The following code was generated by JFlex 1.4.3 on 1/21/14 12:35 PM */
package com.simpleplugin;
@@ -11,7 +11,7 @@ import com.intellij.psi.TokenType;
/**
* This class is a scanner generated by
* JFlex 1.4.3
- * on 2/19/13 7:59 PM from the specification file
+ * on 1/21/14 12:35 PM from the specification file
* /Users/jetbrains/SimplePlugin/src/com/simpleplugin/Simple.flex
*/
class SimpleLexer implements FlexLexer {
@@ -428,7 +428,7 @@ class SimpleLexer implements FlexLexer {
while (true) {
if (zzCurrentPosL < zzEndReadL)
- zzInput = zzBufferL.charAt(zzCurrentPosL++);
+ zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++));
else if (zzAtEOF) {
zzInput = YYEOF;
break zzForAction;
@@ -448,7 +448,7 @@ class SimpleLexer implements FlexLexer {
break zzForAction;
}
else {
- zzInput = zzBufferL.charAt(zzCurrentPosL++);
+ zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++));
}
}
int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
diff --git a/src/com/simpleplugin/SimpleLexerAdapter.java b/src/com/simpleplugin/SimpleLexerAdapter.java
new file mode 100644
index 000000000..662acb59a
--- /dev/null
+++ b/src/com/simpleplugin/SimpleLexerAdapter.java
@@ -0,0 +1,11 @@
+package com.simpleplugin;
+
+import com.intellij.lexer.FlexAdapter;
+
+import java.io.Reader;
+
+public class SimpleLexerAdapter extends FlexAdapter {
+ public SimpleLexerAdapter() {
+ super(new SimpleLexer((Reader) null));
+ }
+}
diff --git a/src/com/simpleplugin/SimpleParserDefinition.java b/src/com/simpleplugin/SimpleParserDefinition.java
index 08a669e7f..6b34ceb0c 100644
--- a/src/com/simpleplugin/SimpleParserDefinition.java
+++ b/src/com/simpleplugin/SimpleParserDefinition.java
@@ -29,7 +29,7 @@ public class SimpleParserDefinition implements ParserDefinition{
@NotNull
@Override
public Lexer createLexer(Project project) {
- return new FlexAdapter(new SimpleLexer((Reader) null));
+ return new SimpleLexerAdapter();
}
@NotNull
diff --git a/src/com/simpleplugin/SimpleSyntaxHighlighter.java b/src/com/simpleplugin/SimpleSyntaxHighlighter.java
index e5fafa471..63e38fa61 100644
--- a/src/com/simpleplugin/SimpleSyntaxHighlighter.java
+++ b/src/com/simpleplugin/SimpleSyntaxHighlighter.java
@@ -35,7 +35,7 @@ public class SimpleSyntaxHighlighter extends SyntaxHighlighterBase {
@NotNull
@Override
public Lexer getHighlightingLexer() {
- return new FlexAdapter(new SimpleLexer((Reader) null));
+ return new SimpleLexerAdapter();
}
@NotNull
diff --git a/src/com/simpleplugin/parser/GeneratedParserUtilBase.java b/src/com/simpleplugin/parser/GeneratedParserUtilBase.java
deleted file mode 100644
index 7122be8d6..000000000
--- a/src/com/simpleplugin/parser/GeneratedParserUtilBase.java
+++ /dev/null
@@ -1,766 +0,0 @@
-package com.simpleplugin.parser;
-
-import com.intellij.lang.*;
-import com.intellij.lang.impl.PsiBuilderAdapter;
-import com.intellij.lang.impl.PsiBuilderImpl;
-import com.intellij.lexer.Lexer;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.text.StringHash;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.TokenType;
-import com.intellij.psi.impl.source.resolve.FileContextUtil;
-import com.intellij.psi.impl.source.tree.CompositePsiElement;
-import com.intellij.psi.tree.ICompositeElementType;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.Function;
-import com.intellij.util.containers.LimitedPool;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @author gregsh
- */
-@SuppressWarnings("StringEquality")
-public class GeneratedParserUtilBase {
-
- private static final Logger LOG = Logger.getInstance("org.intellij.grammar.parser.GeneratedParserUtilBase");
-
- public static final IElementType DUMMY_BLOCK = new DummyBlockElementType();
-
- public interface Parser {
- boolean parse(PsiBuilder builder, int level);
- }
-
- public static final Parser TOKEN_ADVANCER = new Parser() {
- @Override
- public boolean parse(PsiBuilder builder, int level) {
- if (builder.eof()) return false;
- builder.advanceLexer();
- return true;
- }
- };
-
- public static final Parser TRUE_CONDITION = new Parser() {
- @Override
- public boolean parse(PsiBuilder builder, int level) {
- return true;
- }
- };
-
- public static boolean recursion_guard_(PsiBuilder builder_, int level_, String funcName_) {
- if (level_ > 1000) {
- builder_.error("Maximum recursion level (" + 1000 + ") reached in " + funcName_);
- return false;
- }
- return true;
- }
-
- public static void empty_element_parsed_guard_(PsiBuilder builder_, int offset_, String funcName_) {
- builder_.error("Empty element parsed in " + funcName_ +" at offset " + offset_);
- }
-
- public static boolean invalid_left_marker_guard_(PsiBuilder builder_, PsiBuilder.Marker marker_, String funcName_) {
- //builder_.error("Invalid left marker encountered in " + funcName_ +" at offset " + builder_.getCurrentOffset());
- boolean goodMarker = marker_ != null && ((LighterASTNode)marker_).getTokenType() != TokenType.ERROR_ELEMENT;
- if (!goodMarker) return false;
- ErrorState state = ErrorState.get(builder_);
-
- Frame frame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast();
- return frame == null || frame.errorReportedAt <= builder_.getCurrentOffset();
- }
-
- public static boolean consumeTokens(PsiBuilder builder_, int pin_, IElementType... tokens_) {
- ErrorState state = ErrorState.get(builder_);
- if (state.completionState != null && state.predicateSign) {
- addCompletionVariant(state, state.completionState, builder_, tokens_, builder_.getCurrentOffset());
- }
- // suppress single token completion
- CompletionState completionState = state.completionState;
- state.completionState = null;
- boolean result_ = true;
- boolean pinned_ = false;
- for (int i = 0, tokensLength = tokens_.length; i < tokensLength; i++) {
- if (pin_ > 0 && i == pin_) pinned_ = result_;
- if ((result_ || pinned_) && !consumeToken(builder_, tokens_[i])) {
- result_ = false;
- if (pin_ < 0 || pinned_) report_error_(builder_);
- }
- }
- state.completionState = completionState;
- return pinned_ || result_;
- }
-
- public static boolean consumeToken(PsiBuilder builder_, IElementType token) {
- if (nextTokenIsInner(builder_, token, true)) {
- builder_.advanceLexer();
- return true;
- }
- return false;
- }
-
- public static boolean nextTokenIs(PsiBuilder builder_, IElementType token) {
- return nextTokenIsInner(builder_, token, false);
- }
-
- public static boolean nextTokenIsInner(PsiBuilder builder_, IElementType token, boolean force) {
- ErrorState state = ErrorState.get(builder_);
- if (state.completionState != null && !force) return true;
- IElementType tokenType = builder_.getTokenType();
- if (!state.suppressErrors && state.predicateCount < 2) {
- addVariant(state, builder_, token);
- }
- return token == tokenType;
- }
-
- public static boolean replaceVariants(PsiBuilder builder_, int variantCount, String frameName) {
- ErrorState state = ErrorState.get(builder_);
- if (!state.suppressErrors && state.predicateCount < 2 && state.predicateSign) {
- state.clearVariants(true, state.variants.size() - variantCount);
- addVariantInner(state, builder_.getCurrentOffset(), frameName);
- }
- return true;
- }
-
- public static void addVariant(PsiBuilder builder_, String text) {
- addVariant(ErrorState.get(builder_), builder_, text);
- }
-
- private static void addVariant(ErrorState state, PsiBuilder builder_, Object o) {
- int offset = builder_.getCurrentOffset();
- addVariantInner(state, offset, o);
-
- CompletionState completionState = state.completionState;
- if (completionState != null && state.predicateSign) {
- addCompletionVariant(state, completionState, builder_, o, offset);
- }
- }
-
- private static void addVariantInner(ErrorState state, int offset, Object o) {
- Variant variant = state.VARIANTS.alloc().init(offset, o);
- if (state.predicateSign) {
- state.variants.add(variant);
- if (state.lastExpectedVariantOffset < variant.offset) {
- state.lastExpectedVariantOffset = variant.offset;
- }
- }
- else {
- state.unexpected.add(variant);
- }
- }
-
- public static boolean consumeToken(PsiBuilder builder_, String text) {
- ErrorState state = ErrorState.get(builder_);
- if (!state.suppressErrors && state.predicateCount < 2) {
- addVariant(state, builder_, text);
- }
- return consumeTokenInner(builder_, text, state.caseSensitive);
- }
-
- public static boolean consumeTokenInner(PsiBuilder builder_, String text, boolean caseSensitive) {
- final CharSequence sequence = builder_.getOriginalText();
- final int offset = builder_.getCurrentOffset();
- final int endOffset = offset + text.length();
- CharSequence tokenText = sequence.subSequence(offset, Math.min(endOffset, sequence.length()));
-
- if (Comparing.equal(text, tokenText, caseSensitive)) {
- int count = 0;
- while (true) {
- final int nextOffset = builder_.rawTokenTypeStart(++ count);
- if (nextOffset > endOffset) {
- return false;
- }
- else if (nextOffset == endOffset) {
- break;
- }
- }
- while (count-- > 0) builder_.advanceLexer();
- return true;
- }
- return false;
- }
-
- private static void addCompletionVariant(ErrorState state,
- CompletionState completionState,
- PsiBuilder builder_,
- Object o,
- int offset) {
- boolean add = false;
- int diff = completionState.offset - offset;
- String text = completionState.convertItem(o);
- int length = text == null? 0 : text.length();
- if (length == 0) return;
- if (diff == 0) {
- add = true;
- }
- else if (diff > 0 && diff <= length) {
- CharSequence fragment = builder_.getOriginalText().subSequence(offset, completionState.offset);
- add = StringUtil.startsWithIgnoreCase(text, fragment.toString());
- }
- else if (diff < 0) {
- for (int i=-1; ; i--) {
- IElementType type = builder_.rawLookup(i);
- int tokenStart = builder_.rawTokenTypeStart(i);
- if (state.whitespaceTokens.contains(type) || state.commentTokens.contains(type)) {
- diff = completionState.offset - tokenStart;
- }
- else if (type != null && tokenStart < completionState.offset) {
- CharSequence fragment = builder_.getOriginalText().subSequence(tokenStart, completionState.offset);
- if (StringUtil.startsWithIgnoreCase(text, fragment.toString())) {
- diff = completionState.offset - tokenStart;
- }
- break;
- }
- else break;
- }
- add = diff >= 0 && diff < length;
- }
- add = add && length > 1 && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>') &&
- !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5);
- if (add) {
- completionState.items.add(text);
- }
- }
-
-
- public static final String _SECTION_NOT_ = "_SECTION_NOT_";
- public static final String _SECTION_AND_ = "_SECTION_AND_";
- public static final String _SECTION_RECOVER_ = "_SECTION_RECOVER_";
- public static final String _SECTION_GENERAL_ = "_SECTION_GENERAL_";
-
- public static void enterErrorRecordingSection(PsiBuilder builder_, int level, @NotNull String sectionType, @Nullable String frameName) {
- ErrorState state = ErrorState.get(builder_);
- Frame frame = state.FRAMES.alloc().init(builder_.getCurrentOffset(), level, sectionType, frameName, state.variants.size());
- state.levelCheck.add(frame);
- if (sectionType == _SECTION_AND_) {
- if (state.predicateCount == 0 && !state.predicateSign) {
- throw new AssertionError("Incorrect false predicate sign");
- }
- state.predicateCount++;
- }
- else if (sectionType == _SECTION_NOT_) {
- if (state.predicateCount == 0) {
- state.predicateSign = false;
- }
- else {
- state.predicateSign = !state.predicateSign;
- }
- state.predicateCount++;
- }
- }
-
- public static boolean exitErrorRecordingSection(PsiBuilder builder_,
- int level,
- boolean result,
- boolean pinned,
- @NotNull String sectionType,
- @Nullable Parser eatMore) {
- ErrorState state = ErrorState.get(builder_);
-
- Frame frame = state.levelCheck.pollLast();
- int initialOffset = builder_.getCurrentOffset();
- if (frame == null || level != frame.level || !sectionType.equals(frame.section)) {
- LOG.error("Unbalanced error section: got " + new Frame().init(initialOffset, level, sectionType, "", 0) + ", expected " + frame);
- if (frame != null) state.FRAMES.recycle(frame);
- return result;
- }
- if (sectionType == _SECTION_AND_ || sectionType == _SECTION_NOT_) {
- state.predicateCount--;
- if (sectionType == _SECTION_NOT_) state.predicateSign = !state.predicateSign;
- state.FRAMES.recycle(frame);
- return result;
- }
- if (!result && !pinned && initialOffset == frame.offset && state.lastExpectedVariantOffset == frame.offset &&
- frame.name != null && state.variants.size() - frame.variantCount > 1) {
- state.clearVariants(true, frame.variantCount);
- addVariantInner(state, initialOffset, frame.name);
- }
- if (sectionType == _SECTION_RECOVER_ && !state.suppressErrors && eatMore != null) {
- state.suppressErrors = true;
- final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1);
- final int lastErrorPos = getLastVariantOffset(state, initialOffset);
- boolean eatMoreFlag = eatMoreFlagOnce || frame.offset == initialOffset && lastErrorPos > frame.offset;
-
- final LighterASTNode latestDoneMarker =
- (pinned || result) && (state.altMode || lastErrorPos > initialOffset) &&
- eatMoreFlagOnce ? builder_.getLatestDoneMarker() : null;
- PsiBuilder.Marker extensionMarker = null;
- IElementType extensionTokenType = null;
- if (latestDoneMarker instanceof PsiBuilder.Marker) {
- extensionMarker = ((PsiBuilder.Marker)latestDoneMarker).precede();
- extensionTokenType = latestDoneMarker.getTokenType();
- ((PsiBuilder.Marker)latestDoneMarker).drop();
- }
- // advance to the last error pos
- // skip tokens until lastErrorPos. parseAsTree might look better here...
- int parenCount = 0;
- while (eatMoreFlag && builder_.getCurrentOffset() < lastErrorPos) {
- if (state.braces != null) {
- if (builder_.getTokenType() == state.braces[0].getLeftBraceType()) parenCount ++;
- else if (builder_.getTokenType() == state.braces[0].getRightBraceType()) parenCount --;
- }
- builder_.advanceLexer();
- eatMoreFlag = parenCount != 0 || eatMore.parse(builder_, frame.level + 1);
- }
- boolean errorReported = frame.errorReportedAt == initialOffset;
- if (errorReported) {
- if (eatMoreFlag) {
- builder_.advanceLexer();
- parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore);
- }
- }
- else if (eatMoreFlag) {
- String tokenText = builder_.getTokenText();
- String expectedText = state.getExpectedText(builder_);
- PsiBuilder.Marker mark = builder_.mark();
- builder_.advanceLexer();
- final String gotText = !expectedText.isEmpty() ? "got '" + tokenText + "'" : "'" + tokenText + "' unexpected";
- mark.error(expectedText + gotText);
- parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore);
- errorReported = true;
- }
- else if (eatMoreFlagOnce || (!result && frame.offset != builder_.getCurrentOffset())) {
- reportError(state, builder_, true);
- errorReported = true;
- }
- if (extensionMarker != null) {
- extensionMarker.done(extensionTokenType);
- }
- state.suppressErrors = false;
- if (errorReported || result) {
- state.clearVariants(true, 0);
- state.clearVariants(false, 0);
- state.lastExpectedVariantOffset = -1;
- }
- if (!result && eatMoreFlagOnce && frame.offset != builder_.getCurrentOffset()) result = true;
- }
- else if (!result && pinned && frame.errorReportedAt < 0) {
- // do not report if there're errors after current offset
- if (getLastVariantOffset(state, initialOffset) == initialOffset) {
- // do not force, inner recoverRoot might have skipped some tokens
- if (reportError(state, builder_, false)) {
- frame.errorReportedAt = initialOffset;
- }
- }
- }
- // propagate errorReportedAt up the stack to avoid duplicate reporting
- Frame prevFrame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast();
- if (prevFrame != null && prevFrame.errorReportedAt < frame.errorReportedAt) prevFrame.errorReportedAt = frame.errorReportedAt;
- state.FRAMES.recycle(frame);
- return result;
- }
-
- public static boolean report_error_(PsiBuilder builder_, boolean current_) {
- if (!current_) report_error_(builder_);
- return current_;
- }
-
- public static void report_error_(PsiBuilder builder_) {
- ErrorState state = ErrorState.get(builder_);
-
- Frame frame = state.levelCheck.isEmpty()? null : state.levelCheck.getLast();
- if (frame == null) {
- LOG.error("Unbalanced error section: got null , expected " + frame);
- return;
- }
- int offset = builder_.getCurrentOffset();
- if (frame.errorReportedAt < offset && getLastVariantOffset(state, builder_.getCurrentOffset()) <= offset) {
- if (reportError(state, builder_, true)) {
- frame.errorReportedAt = offset;
- }
- }
- }
-
- private static int getLastVariantOffset(ErrorState state, int defValue) {
- return state.lastExpectedVariantOffset < 0? defValue : state.lastExpectedVariantOffset;
- }
-
- private static boolean reportError(ErrorState state, PsiBuilder builder_, boolean force) {
- String expectedText = state.getExpectedText(builder_);
- boolean notEmpty = StringUtil.isNotEmpty(expectedText);
- if (force || notEmpty) {
- final String gotText = builder_.eof()? "unexpected end of file" :
- notEmpty? "got '" + builder_.getTokenText() +"'" :
- "'" + builder_.getTokenText() +"' unexpected";
- builder_.error(expectedText + gotText);
- return true;
- }
- return false;
- }
-
-
- public static final Key COMPLETION_STATE_KEY = Key.create("COMPLETION_STATE_KEY");
-
- public static class CompletionState implements Function