Skip to content

Commit

Permalink
Add preprocessor support to the parser
Browse files Browse the repository at this point in the history
Currently after every lexer advance (and at the very beginning), the
parser will check for a preprocessor begin. Currently the parser just
eats the entire directive without handling it.

The compound statement element had to be modified as these directives
can exist inside a compound statement, but previously they asserted on
finding anything other than a statement or comment.
  • Loading branch information
AbigailBuccaneer committed Apr 22, 2015
1 parent 0b241eb commit ca5372f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/glslplugin/lang/elements/GLSLElementTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class GLSLElementTypes {
public static final IElementType TRANSLATION_UNIT = new GLSLElementType("TRANSLATION_UNIT");
public static final IElementType BLOCK = new GLSLElementType("BLOCK");

public static final IElementType PREPROCESSOR_DIRECTIVE = new GLSLElementType("PREPROCESSOR_DIRECTIVE");

public static final IElementType EMPTY_STATEMENT = new GLSLElementType("EMPTY_STATEMENT");
public static final IElementType JUMP_STATEMENT = new GLSLElementType("JUMP_STATEMENT");

Expand Down
20 changes: 3 additions & 17 deletions src/glslplugin/lang/elements/statements/GLSLCompoundStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import glslplugin.lang.elements.GLSLTokenTypes;
import org.jetbrains.annotations.NotNull;

Expand All @@ -42,23 +43,8 @@ public GLSLCompoundStatement(@NotNull ASTNode astNode) {

@NotNull
public GLSLStatement[] getStatements() {
// convert the list of children to a list of GLSLStatement objects while performing sanity check.
PsiElement[] children = getChildren();
List<GLSLStatement> result = new ArrayList<GLSLStatement>(children.length);
for (PsiElement child : children) {
if (child instanceof GLSLStatement) {
result.add((GLSLStatement) child);
} else {
final ASTNode node = child.getNode();
if (node != null) {
final IElementType type = node.getElementType();
if (!GLSLTokenTypes.COMMENTS.contains(type)) {
throw new RuntimeException("Compound statement contains non-comment, non-statement element.");
}
}
}
}
return result.toArray(new GLSLStatement[result.size()]);
GLSLStatement[] statements = PsiTreeUtil.getChildrenOfType(this, GLSLStatement.class);
return (statements == null) ? new GLSLStatement[0] : statements;
}

public String toString() {
Expand Down
70 changes: 51 additions & 19 deletions src/glslplugin/lang/parser/GLSLParsing.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public class GLSLParsing {
*/
private void skipTo(TokenSet set) {
while (b.getTokenType() != null && set.contains(b.getTokenType())) {
b.advanceLexer();
advanceLexer();
}
}

Expand All @@ -82,7 +82,7 @@ private void skipTo(TokenSet set) {
*/
private void skipTo(IElementType type) {
while (b.getTokenType() != null && b.getTokenType() != type) {
b.advanceLexer();
advanceLexer();
}
}

Expand All @@ -99,7 +99,7 @@ private boolean match(IElementType type, String error) {
}
boolean match = b.getTokenType() == type;
if (match) {
b.advanceLexer();
advanceLexer();
} else {
b.error(error);
}
Expand All @@ -121,7 +121,7 @@ private boolean tryMatch(IElementType... types) {
match |= b.getTokenType() == type;
}
if (match) {
b.advanceLexer();
advanceLexer();
}
return match;
}
Expand All @@ -135,21 +135,53 @@ private boolean tryMatch(IElementType... types) {
private boolean tryMatch(TokenSet types) {
boolean match = types.contains(b.getTokenType());
if (match) {
b.advanceLexer();
advanceLexer();
}
return match;
}

private void advanceLexer() {
b.advanceLexer();
if (b.getTokenType() == PREPROCESSOR_BEGIN) {
parsePreprocessor();
}
}

private void parsePreprocessor() {
// We can't use tryMatch etc. in here because we'll end up
// potentially parsing a preprocessor directive inside this one.
PsiBuilder.Marker preprocessor = b.mark();
while (!b.eof()) {
b.advanceLexer();
if (b.getTokenType() == PREPROCESSOR_END) {
b.advanceLexer();
break;
}
}
preprocessor.done(PREPROCESSOR_DIRECTIVE);

if (b.getTokenType() == PREPROCESSOR_BEGIN) {
parsePreprocessor();
}
}

/**
* Entry for parser. Tries to parse whole shader file.
*/
public void parseTranslationUnit() {
// translation_unit: external_declaration+

PsiBuilder.Marker unit = b.mark();

// We normally parse preprocessor directives whenever we advance the lexer - which means that if the first
// token is a preprocessor directive we won't catch it, so we just parse them all at the beginning here.
while (b.getTokenType() == PREPROCESSOR_BEGIN) {
parsePreprocessor();
}

do {
if (!parseExternalDeclaration()) {
b.advanceLexer();
advanceLexer();
b.error("Unable to parse external declaration.");
}
}
Expand Down Expand Up @@ -278,7 +310,7 @@ private boolean parseExternalDeclaration() {
mark = b.mark();
if(!parseExpression()){
//There is no expression! Consume what triggered me. (Would lead to infinite loop otherwise)
b.advanceLexer();
advanceLexer();
}
tryMatch(SEMICOLON);
mark.error("Expression not allowed here.");
Expand All @@ -287,7 +319,7 @@ private boolean parseExternalDeclaration() {
GLSLTokenTypes.CONSTANT_TOKENS.contains(b.getTokenType())) {
postType.drop();
text = b.getTokenText();
b.advanceLexer();
advanceLexer();
mark.error("Unexpected '" + text + "'");
return true;
} else if (TYPE_SPECIFIER_NONARRAY_TOKENS.contains(b.getTokenType())) {
Expand Down Expand Up @@ -404,7 +436,7 @@ private void eatInvalidOperators() {
PsiBuilder.Marker mark = b.mark();
while (OPERATORS.contains(b.getTokenType())) {
String operator = b.getTokenText();
b.advanceLexer();
advanceLexer();
mark.error("Unexpected operator '" + operator + "'.");
mark = b.mark();
}
Expand Down Expand Up @@ -557,7 +589,7 @@ private void parseForInitStatement() {
if (b.getTokenType() == IDENTIFIER) {
// needs lookahead
PsiBuilder.Marker rollback = b.mark();
b.advanceLexer();
advanceLexer();
if (b.getTokenType() == IDENTIFIER) {
// IDENTIFIER IDENTIFIER means declaration statement
// where the first is the type specifier
Expand Down Expand Up @@ -1066,7 +1098,7 @@ private void parseParameterList() {
PsiBuilder.Marker mark = b.mark();

if (b.getTokenType() == VOID_TYPE) {
b.advanceLexer();
advanceLexer();
} else if (b.getTokenType() == RIGHT_PAREN) {
// do nothing
} else if (parseAssignmentExpression()) {
Expand Down Expand Up @@ -1094,16 +1126,16 @@ private boolean parsePrimaryExpression() {
final IElementType type = b.getTokenType();
if (type == IDENTIFIER) {
final PsiBuilder.Marker mark2 = b.mark();
b.advanceLexer();
advanceLexer();
mark2.done(VARIABLE_NAME);
mark.done(VARIABLE_NAME_EXPRESSION);
return true;
} else if (type == INTEGER_CONSTANT || type == FLOAT_CONSTANT || type == BOOL_CONSTANT) {
b.advanceLexer();
advanceLexer();
mark.done(CONSTANT_EXPRESSION);
return true;
} else if (type == LEFT_PAREN) {
b.advanceLexer();
advanceLexer();
if (!parseExpression()) {
if (b.getTokenType() == RIGHT_PAREN) {
b.error("Expected expression after '('");
Expand All @@ -1126,7 +1158,7 @@ private String parseIdentifier() {
boolean success = b.getTokenType() == IDENTIFIER;
if (success) {
String name = b.getTokenText();
b.advanceLexer();
advanceLexer();
mark.done(VARIABLE_NAME);
return name;
} else {
Expand All @@ -1140,7 +1172,7 @@ private String parseFieldIdentifier() {
boolean success = b.getTokenType() == IDENTIFIER;
if (success) {
String name = b.getTokenText();
b.advanceLexer();
advanceLexer();
mark.done(FIELD_NAME);
return name;
} else {
Expand Down Expand Up @@ -1185,7 +1217,7 @@ private boolean parseTypeSpecifierNoArray() {
parseStructSpecifier();
mark.done(TYPE_SPECIFIER_STRUCT);
} else if (TYPE_SPECIFIER_NONARRAY_TOKENS.contains(b.getTokenType())) {
b.advanceLexer();
advanceLexer();
mark.done(TYPE_SPECIFIER_PRIMITIVE);
} else if (b.getTokenType() == IDENTIFIER) {
parseIdentifier();
Expand Down Expand Up @@ -1275,7 +1307,7 @@ private void parseStructOrParameterDeclarator(IElementType type) {
parseIdentifier();

if (b.getTokenType() == LEFT_BRACKET) {
b.advanceLexer();
advanceLexer();
parseConstantExpression();
match(RIGHT_BRACKET, "Expected ']' after constant expression.");
}
Expand All @@ -1297,7 +1329,7 @@ private void parseQualifierList(boolean validPlacement) {
while (QUALIFIER_TOKENS.contains(b.getTokenType())) {
final PsiBuilder.Marker mark2 = b.mark();

b.advanceLexer();
advanceLexer();

if(validPlacement)
mark2.done(QUALIFIER);
Expand Down

0 comments on commit ca5372f

Please sign in to comment.