Soft keywords fixed

This commit is contained in:
Andrey Breslav
2010-12-21 18:46:49 +03:00
parent c614d1dadc
commit 4d54f704b9
13 changed files with 1295 additions and 142 deletions
@@ -13,9 +13,9 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
* @author abreslav
*/
/*package*/ class AbstractJetParsing {
protected final SemanticWitespaceAwarePsiBuilder myBuilder;
protected final SemanticWhitespaceAwarePsiBuilder myBuilder;
public AbstractJetParsing(SemanticWitespaceAwarePsiBuilder builder) {
public AbstractJetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
this.myBuilder = builder;
}
@@ -12,7 +12,7 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
* @author abreslav
*/
public class JetExpressionParsing extends AbstractJetParsing {
public JetExpressionParsing(SemanticWitespaceAwarePsiBuilder builder) {
public JetExpressionParsing(SemanticWhitespaceAwarePsiBuilder builder) {
super(builder);
}
@@ -8,12 +8,11 @@ import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
public class JetParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType iElementType, PsiBuilder psiBuilder) {
new JetParsing(new SemanticWitespaceAwarePsiBuilder(psiBuilder)).parseFile();
new JetParsing(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder)).parseFile();
return psiBuilder.getTreeBuilt();
}
}
@@ -40,7 +40,7 @@ public class JetParsing extends AbstractJetParsing {
private final JetExpressionParsing myExpressionParsing;
public JetParsing(SemanticWitespaceAwarePsiBuilder builder) {
public JetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
super(builder);
this.myExpressionParsing = new JetExpressionParsing(builder);
}
@@ -300,8 +300,8 @@ public class JetParsing extends AbstractJetParsing {
while (!eof()) {
if (at(LBRACKET)) {
parseAttributeAnnotation();
} else if (MODIFIER_KEYWORDS.contains(tt())) {
advance();
} else if (atSet(MODIFIER_KEYWORDS)) {
advance(); // MODIFIER
}
else {
if (!parseModifierSoftKeyword()) break;
@@ -365,8 +365,8 @@ public class JetParsing extends AbstractJetParsing {
* ;
*/
private JetNodeType parseNamespaceBlock() {
assert at(NAMESPACE);
advance(); // NAMESPACE
assert at(NAMESPACE_KEYWORD);
advance(); // NAMESPACE_KEYWORD
if (at(LBRACE)) {
error("Expecting namespace name");
@@ -460,6 +460,8 @@ public class JetParsing extends AbstractJetParsing {
private void parseMemberDeclaration() {
PsiBuilder.Marker decl = mark();
parseModifierList();
IElementType keywordToken = tt();
JetNodeType declType = null;
if (keywordToken == CLASS_KEYWORD) {
@@ -490,7 +492,7 @@ public class JetParsing extends AbstractJetParsing {
}
if (declType == null) {
errorAndAdvance("Expecting namespace or top level declaration");
errorAndAdvance("Expecting member declaration");
decl.drop();
}
else {
@@ -610,17 +612,18 @@ public class JetParsing extends AbstractJetParsing {
TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, EOL_OR_SEMICOLON);
int lastDot = findLastDotBefore(propertyNameFollow);
int lastDot = findLastBefore(TokenSet.create(DOT), propertyNameFollow, true);
if (lastDot == -1) {
parseAttributeList();
expect(IDENTIFIER, "Expecting property name or receiver type", propertyNameFollow);
}
else {
// The code below is NOT REENTRANT
myBuilder.setEOFPosition(lastDot);
parseTypeRef();
myBuilder.unSetEOFPosition();
createTruncatedBuilder(lastDot).parseTypeRef();
// // The code below is NOT REENTRANT
// myBuilder.setEOFPosition(lastDot);
// parseTypeRef();
// myBuilder.unSetEOFPosition();
expect(DOT, "Expecting '.' before a property name", propertyNameFollow);
expect(IDENTIFIER, "Expecting property name", propertyNameFollow);
@@ -661,6 +664,10 @@ public class JetParsing extends AbstractJetParsing {
return PROPERTY;
}
private JetParsing createTruncatedBuilder(int eofPosition) {
return new JetParsing(new TruncatedSemanticWhitespaceAwarePsiBuilder(myBuilder, eofPosition));
}
/*
* getter
* : modifiers
@@ -702,16 +709,17 @@ public class JetParsing extends AbstractJetParsing {
advance(); // FUN_KEYWORD
int lastDot = findLastDotBefore(TokenSet.create(LPAR));
int lastDot = findLastBefore(TokenSet.create(DOT), TokenSet.create(LPAR), true);
if (lastDot == -1) { // There's no explicit receiver type specified
parseAttributeList();
expect(IDENTIFIER, "Expecting function name or receiver type");
} else {
// The code below in NOT REENTRANT
myBuilder.setEOFPosition(lastDot);
parseTypeRef();
myBuilder.unSetEOFPosition();
createTruncatedBuilder(lastDot).parseTypeRef();
// // The code below in NOT REENTRANT
// myBuilder.setEOFPosition(lastDot);
// parseTypeRef();
// myBuilder.unSetEOFPosition();
TokenSet functionNameFollow = TokenSet.create(LT, LPAR, COLON, EQ);
expect(DOT, "Expecting '.' before a function name", functionNameFollow);
@@ -744,21 +752,22 @@ public class JetParsing extends AbstractJetParsing {
* Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a
* top-level occurrence of a token from the <code>stopSet</code>
*/
private int findLastDotBefore(TokenSet stopSet) {
private int findLastBefore(TokenSet lookFor, TokenSet stopAt, boolean dontStopRightAfterOccurrence) {
PsiBuilder.Marker currentPosition = mark();
int lastDot = -1;
int lastOccurrence = -1;
int openAngleBrackets = 0;
int openBraces = 0;
int openParentheses = 0;
int openBrackets = 0;
IElementType previousToken = null;
while (!eof()) {
if (atSet(stopSet)) {
if (atSet(stopAt)) {
if (openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0
&& previousToken != DOT) break;
&& (!dontStopRightAfterOccurrence
|| !lookFor.contains(previousToken))) break;
}
if (at(LPAR)) {
openParentheses++;
@@ -784,18 +793,18 @@ public class JetParsing extends AbstractJetParsing {
else if (at(RBRACKET)) {
openBrackets--;
}
else if (at(DOT)
else if (atSet(lookFor)
&& openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0) {
lastDot = myBuilder.getCurrentOffset();
lastOccurrence = myBuilder.getCurrentOffset();
}
previousToken = tt();
advance(); // skip token
}
currentPosition.rollbackTo();
return lastDot;
return lastOccurrence ;
}
/*
@@ -1025,13 +1034,20 @@ public class JetParsing extends AbstractJetParsing {
* ;
*/
private void parseTypeParameter() {
if (TYPE_PARAMETER_GT_RECOVERY_SET.contains(tt())) {
if (atSet(TYPE_PARAMETER_GT_RECOVERY_SET)) {
error("Type parameter declaration expected");
return;
}
PsiBuilder.Marker mark = mark();
parseModifierList();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, GT, COLON), false);
createTruncatedBuilder(lastId).parseModifierList();
// // The code below is NOT REENTRANT
// myBuilder.setEOFPosition(lastId);
// parseModifierList();
// myBuilder.unSetEOFPosition();
expect(IDENTIFIER, "Type parameter name expected", TokenSet.EMPTY);
// TODO : other constraints
@@ -1226,7 +1242,13 @@ public class JetParsing extends AbstractJetParsing {
if (!at(RPAR)) {
while (true) {
if (at(COMMA)) errorAndAdvance("Expecting a parameter declaration");
if (at(COMMA)) {
errorAndAdvance("Expecting a parameter declaration");
}
else if (at(RPAR)) {
error("Expecting a parameter declaration");
break;
}
if (!parseValueParameter()) {
if (isFunctionTypeContents) {
parseModifierList(); // lazy, out, ref
@@ -1251,7 +1273,13 @@ public class JetParsing extends AbstractJetParsing {
private boolean parseValueParameter() {
PsiBuilder.Marker parameter = mark();
parseModifierList();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, RPAR, COLON), false);
createTruncatedBuilder(lastId).parseModifierList();
// // The code below is NOT REENTRANT
// myBuilder.setEOFPosition(lastId);
// parseModifierList();
// myBuilder.unSetEOFPosition();
if (!parseFunctionParameterRest()) {
parameter.rollbackTo();
return false;
@@ -0,0 +1,10 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
/**
* @author abreslav
*/
public interface SemanticWhitespaceAwarePsiBuilder extends PsiBuilder {
boolean eolInLastWhitespace();
}
@@ -8,7 +8,7 @@ import com.intellij.psi.tree.IElementType;
/**
* @author abreslav
*/
public class SemanticWitespaceAwarePsiBuilder extends PsiBuilderAdapter {
public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter implements SemanticWhitespaceAwarePsiBuilder {
private final WhitespaceSkippedCallback myWhitespaceSkippedCallback = new WhitespaceSkippedCallback() {
public void onSkip(IElementType type, int start, int end) {
CharSequence whitespace = getOriginalText();
@@ -23,9 +23,8 @@ public class SemanticWitespaceAwarePsiBuilder extends PsiBuilderAdapter {
};
private boolean myEOLInLastWhitespace;
private int myEOFPosition = -1;
public SemanticWitespaceAwarePsiBuilder(final PsiBuilder delegate) {
public SemanticWhitespaceAwarePsiBuilderImpl(final PsiBuilder delegate) {
super(delegate);
delegate.setWhitespaceSkippedCallback(myWhitespaceSkippedCallback);
}
@@ -36,33 +35,8 @@ public class SemanticWitespaceAwarePsiBuilder extends PsiBuilderAdapter {
super.advanceLexer();
}
@Override
public boolean eolInLastWhitespace() {
return myEOLInLastWhitespace;
}
@Override
public boolean eof() {
if (super.eof()) return true;
return myEOFPosition >= 0 && getCurrentOffset() >= myEOFPosition;
}
@Override
public String getTokenText() {
if (eof()) return null;
return super.getTokenText();
}
@Override
public IElementType getTokenType() {
if (eof()) return null;
return super.getTokenType();
}
public void setEOFPosition(int myEOFPosition) {
this.myEOFPosition = myEOFPosition;
}
public void unSetEOFPosition() {
this.myEOFPosition = -1;
}
}
@@ -0,0 +1,44 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.psi.tree.IElementType;
/**
* @author abreslav
*/
public class TruncatedSemanticWhitespaceAwarePsiBuilder extends PsiBuilderAdapter implements SemanticWhitespaceAwarePsiBuilder {
private final SemanticWhitespaceAwarePsiBuilder myBuilder;
private final int myEOFPosition;
public TruncatedSemanticWhitespaceAwarePsiBuilder(SemanticWhitespaceAwarePsiBuilder myBuilder, int eofPosition) {
super(myBuilder);
this.myBuilder = myBuilder;
this.myEOFPosition = eofPosition;
}
@Override
public boolean eolInLastWhitespace() {
return myBuilder.eolInLastWhitespace();
}
@Override
public boolean eof() {
if (super.eof()) return true;
return myEOFPosition >= 0 && getCurrentOffset() >= myEOFPosition;
}
@Override
public String getTokenText() {
if (eof()) return null;
return super.getTokenText();
}
@Override
public IElementType getTokenType() {
if (eof()) return null;
return super.getTokenType();
}
}