mirror of
https://github.com/ilyakooo0/intellij-haskell.git
synced 2024-09-11 14:56:19 +03:00
Fix parser in case OPTIONS_GHC pragma contains field/option that starts with --. Fix issue #382.
This commit is contained in:
parent
7a39d41717
commit
88ee8d19ca
@ -139,6 +139,8 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
r = newconstr_fielddecl(b, 0);
|
||||
} else if (t == HS_NEWTYPE_DECLARATION) {
|
||||
r = newtype_declaration(b, 0);
|
||||
} else if (t == HS_OPTIONS_GHC_PRAGMA) {
|
||||
r = options_ghc_pragma(b, 0);
|
||||
} else if (t == HS_OTHER_PRAGMA) {
|
||||
r = other_pragma(b, 0);
|
||||
} else if (t == HS_OVERLAP_PRAGMA) {
|
||||
@ -1497,7 +1499,7 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// COMMENT | NCOMMENT | HADDOCK | NHADDOCK | NOT_TERMINATED_COMMENT
|
||||
// COMMENT | NCOMMENT | HADDOCK | NHADDOCK | NOT_TERMINATED_COMMENT | NOT_TERMINATED_OPTIONS_GHC
|
||||
public static boolean comments(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "comments")) return false;
|
||||
boolean r;
|
||||
@ -1507,6 +1509,7 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
if (!r) r = consumeToken(b, HS_HADDOCK);
|
||||
if (!r) r = consumeToken(b, HS_NHADDOCK);
|
||||
if (!r) r = consumeToken(b, HS_NOT_TERMINATED_COMMENT);
|
||||
if (!r) r = consumeToken(b, HS_NOT_TERMINATED_OPTIONS_GHC);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
@ -2940,7 +2943,7 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// (file_header_pragma onl)*
|
||||
// ((file_header_pragma | options_ghc_pragma) onl)*
|
||||
public static boolean file_header(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header")) return false;
|
||||
Marker m = enter_section_(b, l, _NONE_, HS_FILE_HEADER, "<file header>");
|
||||
@ -2953,38 +2956,35 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// file_header_pragma onl
|
||||
// (file_header_pragma | options_ghc_pragma) onl
|
||||
private static boolean file_header_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header_0")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = file_header_pragma(b, l + 1);
|
||||
r = file_header_0_0(b, l + 1);
|
||||
r = r && onl(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// file_header_pragma | options_ghc_pragma
|
||||
private static boolean file_header_0_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header_0_0")) return false;
|
||||
boolean r;
|
||||
r = file_header_pragma(b, l + 1);
|
||||
if (!r) r = options_ghc_pragma(b, l + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// pragma NEWLINE | pragma
|
||||
// pragma
|
||||
public static boolean file_header_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = file_header_pragma_0(b, l + 1);
|
||||
if (!r) r = pragma(b, l + 1);
|
||||
exit_section_(b, m, HS_FILE_HEADER_PRAGMA, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// pragma NEWLINE
|
||||
private static boolean file_header_pragma_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header_pragma_0")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = pragma(b, l + 1);
|
||||
r = r && consumeToken(b, HS_NEWLINE);
|
||||
exit_section_(b, m, null, r);
|
||||
exit_section_(b, m, HS_FILE_HEADER_PRAGMA, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -4831,6 +4831,18 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// OPTIONS_GHC
|
||||
public static boolean options_ghc_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "options_ghc_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_OPTIONS_GHC)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = consumeToken(b, HS_OPTIONS_GHC);
|
||||
exit_section_(b, m, HS_OPTIONS_GHC_PRAGMA, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// pragma
|
||||
public static boolean other_pragma(PsiBuilder b, int l) {
|
||||
|
@ -1,13 +1,16 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package intellij.haskell.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface HaskellFileHeader extends HaskellCompositeElement {
|
||||
|
||||
@NotNull
|
||||
List<HaskellFileHeaderPragma> getFileHeaderPragmaList();
|
||||
@NotNull
|
||||
List<HaskellFileHeaderPragma> getFileHeaderPragmaList();
|
||||
|
||||
@NotNull
|
||||
List<HaskellOptionsGhcPragma> getOptionsGhcPragmaList();
|
||||
|
||||
}
|
||||
|
6
gen/intellij/haskell/psi/HaskellOptionsGhcPragma.java
Normal file
6
gen/intellij/haskell/psi/HaskellOptionsGhcPragma.java
Normal file
@ -0,0 +1,6 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package intellij.haskell.psi;
|
||||
|
||||
public interface HaskellOptionsGhcPragma extends HaskellCompositeElement {
|
||||
|
||||
}
|
@ -66,6 +66,7 @@ public interface HaskellTypes {
|
||||
IElementType HS_NEWCONSTR = new HaskellCompositeElementType("HS_NEWCONSTR");
|
||||
IElementType HS_NEWCONSTR_FIELDDECL = new HaskellCompositeElementType("HS_NEWCONSTR_FIELDDECL");
|
||||
IElementType HS_NEWTYPE_DECLARATION = new HaskellCompositeElementType("HS_NEWTYPE_DECLARATION");
|
||||
IElementType HS_OPTIONS_GHC_PRAGMA = new HaskellCompositeElementType("HS_OPTIONS_GHC_PRAGMA");
|
||||
IElementType HS_OTHER_PRAGMA = new HaskellCompositeElementType("HS_OTHER_PRAGMA");
|
||||
IElementType HS_OVERLAP_PRAGMA = new HaskellCompositeElementType("HS_OVERLAP_PRAGMA");
|
||||
IElementType HS_QUALIFIER = new HaskellCompositeElementType("HS_QUALIFIER");
|
||||
@ -151,8 +152,10 @@ public interface HaskellTypes {
|
||||
IElementType HS_NEWTYPE = new HaskellTokenType("NEWTYPE");
|
||||
IElementType HS_NHADDOCK = new HaskellTokenType("NHADDOCK");
|
||||
IElementType HS_NOT_TERMINATED_COMMENT = new HaskellTokenType("NOT_TERMINATED_COMMENT");
|
||||
IElementType HS_NOT_TERMINATED_OPTIONS_GHC = new HaskellTokenType("NOT_TERMINATED_OPTIONS_GHC");
|
||||
IElementType HS_OCTAL = new HaskellTokenType("OCTAL");
|
||||
IElementType HS_OF = new HaskellTokenType("OF");
|
||||
IElementType HS_OPTIONS_GHC = new HaskellTokenType("OPTIONS_GHC");
|
||||
IElementType HS_PRAGMA_END = new HaskellTokenType("PRAGMA_END");
|
||||
IElementType HS_PRAGMA_START = new HaskellTokenType("PRAGMA_START");
|
||||
IElementType HS_QUASIQUOTE = new HaskellTokenType("QUASIQUOTE");
|
||||
@ -293,6 +296,8 @@ public interface HaskellTypes {
|
||||
return new HaskellNewconstrFielddeclImpl(node);
|
||||
} else if (type == HS_NEWTYPE_DECLARATION) {
|
||||
return new HaskellNewtypeDeclarationImpl(node);
|
||||
} else if (type == HS_OPTIONS_GHC_PRAGMA) {
|
||||
return new HaskellOptionsGhcPragmaImpl(node);
|
||||
} else if (type == HS_OTHER_PRAGMA) {
|
||||
return new HaskellOtherPragmaImpl(node);
|
||||
} else if (type == HS_OVERLAP_PRAGMA) {
|
||||
|
@ -239,6 +239,10 @@ public class HaskellVisitor extends PsiElementVisitor {
|
||||
visitDataConstructorDeclarationElement(o);
|
||||
}
|
||||
|
||||
public void visitOptionsGhcPragma(@NotNull HaskellOptionsGhcPragma o) {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
||||
public void visitOtherPragma(@NotNull HaskellOtherPragma o) {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
@ -1,34 +1,42 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package intellij.haskell.psi.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import static intellij.haskell.psi.HaskellTypes.*;
|
||||
import intellij.haskell.psi.*;
|
||||
import intellij.haskell.psi.HaskellFileHeader;
|
||||
import intellij.haskell.psi.HaskellFileHeaderPragma;
|
||||
import intellij.haskell.psi.HaskellOptionsGhcPragma;
|
||||
import intellij.haskell.psi.HaskellVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HaskellFileHeaderImpl extends HaskellCompositeElementImpl implements HaskellFileHeader {
|
||||
|
||||
public HaskellFileHeaderImpl(ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
public HaskellFileHeaderImpl(ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull HaskellVisitor visitor) {
|
||||
visitor.visitFileHeader(this);
|
||||
}
|
||||
public void accept(@NotNull HaskellVisitor visitor) {
|
||||
visitor.visitFileHeader(this);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof HaskellVisitor) accept((HaskellVisitor)visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof HaskellVisitor) accept((HaskellVisitor) visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<HaskellFileHeaderPragma> getFileHeaderPragmaList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, HaskellFileHeaderPragma.class);
|
||||
}
|
||||
@Override
|
||||
@NotNull
|
||||
public List<HaskellFileHeaderPragma> getFileHeaderPragmaList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, HaskellFileHeaderPragma.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<HaskellOptionsGhcPragma> getOptionsGhcPragmaList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, HaskellOptionsGhcPragma.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package intellij.haskell.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import intellij.haskell.psi.HaskellOptionsGhcPragma;
|
||||
import intellij.haskell.psi.HaskellVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class HaskellOptionsGhcPragmaImpl extends HaskellCompositeElementImpl implements HaskellOptionsGhcPragma {
|
||||
|
||||
public HaskellOptionsGhcPragmaImpl(ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull HaskellVisitor visitor) {
|
||||
visitor.visitOptionsGhcPragma(this);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof HaskellVisitor) accept((HaskellVisitor) visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,9 @@ import static intellij.haskell.psi.HaskellTypes.*;
|
||||
private int commentStart;
|
||||
private int commentDepth;
|
||||
|
||||
private int optionsGhcStart;
|
||||
private int optionsGhcDepth;
|
||||
|
||||
private int haddockStart;
|
||||
private int haddockDepth;
|
||||
|
||||
@ -29,7 +32,7 @@ import static intellij.haskell.psi.HaskellTypes.*;
|
||||
private int qqDepth;
|
||||
%}
|
||||
|
||||
%xstate NCOMMENT, NHADDOCK, QQ
|
||||
%xstate NCOMMENT, NHADDOCK, QQ, OPTIONS_GHC
|
||||
|
||||
newline = \r|\n|\r\n
|
||||
unispace = \x05
|
||||
@ -199,6 +202,31 @@ nhaddock_start = {left_brace}{dash}{white_char}?{vertical_bar}
|
||||
}
|
||||
|
||||
|
||||
<OPTIONS_GHC> {
|
||||
<<EOF>> {
|
||||
int state = yystate();
|
||||
yybegin(YYINITIAL);
|
||||
zzStartRead = optionsGhcStart;
|
||||
return HS_NOT_TERMINATED_OPTIONS_GHC;
|
||||
}
|
||||
|
||||
{pragma_end} {
|
||||
int state = yystate();
|
||||
yybegin(YYINITIAL);
|
||||
zzStartRead = optionsGhcStart;
|
||||
return HS_OPTIONS_GHC;
|
||||
}
|
||||
|
||||
.|{white_char}|{newline} {}
|
||||
}
|
||||
|
||||
{pragma_start} {white_char}* "OPTIONS_GHC" {
|
||||
yybegin(OPTIONS_GHC);
|
||||
optionsGhcDepth = 0;
|
||||
optionsGhcStart = getTokenStart();
|
||||
}
|
||||
|
||||
|
||||
<QQ> {
|
||||
{left_bracket} ({var_id}|{con_id}|{dot})* {vertical_bar} {
|
||||
qqDepth++;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,13 +55,13 @@
|
||||
program ::= onl shebang_line? onl file_header onl module_body
|
||||
|
||||
shebang_line ::= "#!" general_id+
|
||||
file_header ::= (file_header_pragma onl)*
|
||||
options_ghc_pragma ::= OPTIONS_GHC
|
||||
file_header ::= ((file_header_pragma | options_ghc_pragma) onl)*
|
||||
private pragma ::= PRAGMA_START (onl CON_ID? onl general_pragma_content? onl PRAGMA_END)+ {pin=1}
|
||||
file_header_pragma ::= pragma NEWLINE | pragma
|
||||
file_header_pragma ::= pragma
|
||||
|
||||
other_pragma ::= pragma
|
||||
|
||||
// TODO Add all GHC options
|
||||
general_pragma_content ::= (CON_ID | VAR_ID | CONSYM_ID | VARSYM_ID |
|
||||
LEFT_PAREN | RIGHT_PAREN | FLOAT | UNDERSCORE |
|
||||
SEMICOLON | LEFT_BRACKET | RIGHT_BRACKET | literal | LEFT_BRACE | RIGHT_BRACE |
|
||||
@ -153,7 +153,7 @@ private onls ::= (&<<containsSpaces>> NEWLINE | DIRECTIVE NEWLINE
|
||||
private nls ::= (&<<containsSpaces>> NEWLINE)+ // multiple new lines and spaces
|
||||
private oonls ::= (&<<containsSpaces>> NEWLINE)? // optional one (new line and spaces)
|
||||
|
||||
comments ::= COMMENT | NCOMMENT | HADDOCK | NHADDOCK | NOT_TERMINATED_COMMENT // rule is necessary to refer to various comment types in code
|
||||
comments ::= COMMENT | NCOMMENT | HADDOCK | NHADDOCK | NOT_TERMINATED_COMMENT | NOT_TERMINATED_OPTIONS_GHC // rule is necessary to refer to various comment types in code
|
||||
|
||||
modid ::= (conid DOT)* conid {pin=1 stubClass = "intellij.haskell.psi.stubs.HaskellModidStub"}
|
||||
|
||||
|
@ -16,10 +16,12 @@ class HaskellHighlightingAnnotator extends Annotator {
|
||||
.setTextAttributes(HaskellSyntaxHighlighter.Keyword)
|
||||
case psi: HaskellFileHeaderPragma => psi.getGeneralPragmaContentList.forEach((t: HaskellGeneralPragmaContent) =>
|
||||
holder.createInfoAnnotation(t, null).setTextAttributes(HaskellSyntaxHighlighter.PragmaContent))
|
||||
case psi: HaskellOptionsGhcPragma =>
|
||||
holder.createInfoAnnotation(psi, null).setTextAttributes(HaskellSyntaxHighlighter.PragmaContent)
|
||||
case psi: HaskellTypeSignature => holder.createInfoAnnotation(psi.getFirstChild, null)
|
||||
.setTextAttributes(HaskellSyntaxHighlighter.FunctionName)
|
||||
.setTextAttributes(HaskellSyntaxHighlighter.FunctionName)
|
||||
case psi: HaskellStringLiteralElementImpl => holder.createInfoAnnotation(psi, null)
|
||||
.setTextAttributes(HaskellSyntaxHighlighter.String)
|
||||
.setTextAttributes(HaskellSyntaxHighlighter.String)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user