Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multi line separator #130

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/main/grammar/StructurizrDSL.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ statement ::= scriptStatement
| blockStatement
| singleLineStatement
| rawBlockStatement
| lineCommentStatement
| blockCommentStatement

explicitRelationshipStatement ::= relationshipSource relationshipKeyword relationshipDestination argument* block? lf_eof
implicitRelationshipStatement ::= relationshipKeyword relationshipDestination argument* block? lf_eof
Expand All @@ -53,21 +51,18 @@ relationshipKeyword ::= '->'
relationshipDestination ::= UNQUOTED_TEXT

animationStatement ::= animationKeyword animationBlock lf_eof
animationBlock ::= '{' CRLF (identifierReferencesStatement | lineCommentStatement | blockCommentStatement)* '}'
animationBlock ::= '{' CRLF (identifierReferencesStatement)* '}'
animationKeyword ::= 'animation'
identifierReferencesStatement ::= identifierReference* CRLF

lineCommentStatement ::= LINE_COMMENT lf_eof
blockCommentStatement ::= BLOCK_COMMENT lf_eof

scriptStatement ::= scriptKeyword argument* scriptBlock lf_eof
scriptKeyword ::= '!script'
scriptBlock ::= '{' SCRIPT_TEXT '}'

propertiesStatement ::= propertiesKeyword propertiesBlock lf_eof
propertiesKeyword ::= 'perspectives' | 'properties' | 'users'
propertiesBlock ::= '{' CRLF propertiesBlockElement* '}'
private propertiesBlockElement ::= propertyDefinition | lineCommentStatement | blockCommentStatement
private propertiesBlockElement ::= propertyDefinition
propertyDefinition ::= propertyDefinitionPart+ CRLF
propertyDefinitionPart ::= text

Expand Down
126 changes: 72 additions & 54 deletions src/main/grammar/StructurizrDSL.flex
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nl.dirkgroot.structurizr.dsl;

import com.intellij.lexer.FlexLexer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import static com.intellij.psi.TokenType.BAD_CHARACTER;
import static com.intellij.psi.TokenType.WHITE_SPACE;
Expand All @@ -12,20 +13,6 @@ import static nl.dirkgroot.structurizr.dsl.psi.SDTypes.*;
public StructurizrDSLLexer() {
this(null);
}

private void startScript() {
braces = 0;
yybegin(EXPECT_SCRIPT);
}

private void endScript() {
braces = 0;
yybegin(YYINITIAL);
}
%}

%{
private int braces = 0;
%}

%ignorecase
Expand All @@ -36,69 +23,100 @@ import static nl.dirkgroot.structurizr.dsl.psi.SDTypes.*;
%type IElementType
%unicode

%state EXPECT_NON_COMMENT
%state EXPECT_SCRIPT_ARGUMENTS
%state EXPECT_SCRIPT
%state EXPECT_NON_COMMENT EXPECT_SCRIPT_ARGUMENTS
%xstate BLOCK_COMMENT_BODY EXPECT_SCRIPT

EOL=[\r\n]
NonEOL=[^{EOL}]
CrLf=\r\n|{EOL}
Space=[\p{Whitespace}--{EOL}]
MultiLineSeparator=\\{CrLf}
SpaceOrMultiLineSeparator=({Space}|{MultiLineSeparator})
WhiteSpace={SpaceOrMultiLineSeparator}+
MultiLineSeparatorsWithSpaces={MultiLineSeparator}{SpaceOrMultiLineSeparator}*
WhiteSpaceWithNewLines=({CrLf}|{SpaceOrMultiLineSeparator})+

CRLF=\r|\n|\r\n
WHITE_SPACE=[\ \t\f]+
EscapedSymbol=\\\S
EscapeOrMultiLineSeparator={EscapedSymbol}|{MultiLineSeparator}
NonCrLf=({EscapeOrMultiLineSeparator}|{NonEOL})

QUOTED_TEXT=\" [^\"\r\n]* \"?
UNQUOTED_TEXT=[^\s\"\r\n]+
QuotedText=\" ({EscapeOrMultiLineSeparator}|[{NonEOL}--[\"]])* \"?
UnquotedText=({EscapedSymbol}|[^\s\"])({MultiLineSeparatorsWithSpaces}?({EscapedSymbol}|\S))*

LINE_COMMENT=("//"|"#") [^\r\n]*
BLOCK_COMMENT="/*" ( ([^"*"]|[\r\n])* ("*"+ [^"*""/"] )? )* ("*" | "*"+"/")?
LineComment=("/"{MultiLineSeparatorsWithSpaces}?"/"|"#") {NonCrLf}*
BlockCommentStart="/"{MultiLineSeparatorsWithSpaces}?"*"
BlockCommentEnd="*"{MultiLineSeparatorsWithSpaces}?"/"

SCRIPT_TEXT=[^\r\n{}]+
ScriptText=({EscapeOrMultiLineSeparator}|{NonEOL})

Arrow=-{MultiLineSeparatorsWithSpaces}?>
%%

<YYINITIAL,EXPECT_NON_COMMENT,EXPECT_SCRIPT_ARGUMENTS> {
{WHITE_SPACE} { return WHITE_SPACE; }
^{WHITE_SPACE}? {CRLF} { return WHITE_SPACE; }
// XSTATES

<BLOCK_COMMENT_BODY> {
// block comments must end with '*/' at the end of the line
{NonCrLf}*{BlockCommentEnd}{SpaceOrMultiLineSeparator}*{CrLf}? {
int closingSlashPos = StringUtil.lastIndexOf(yytext(), '/', 0, yylength());
yypushback(yylength() - 1 - closingSlashPos);
yybegin(YYINITIAL);
return BLOCK_COMMENT;
}
{NonCrLf}*{CrLf} { }
{NonCrLf}+ {
// EOF met
yybegin(YYINITIAL);
return BLOCK_COMMENT;
}
}

<YYINITIAL> {
{BLOCK_COMMENT} { return BLOCK_COMMENT; }
{LINE_COMMENT} { return LINE_COMMENT; }
<EXPECT_SCRIPT> {
{SpaceOrMultiLineSeparator}*\}{SpaceOrMultiLineSeparator}*{CrLf}? {
int rbracePosExclusive = StringUtil.lastIndexOf(yytext(), '}', 0, yylength());
yypushback(yylength() - rbracePosExclusive);
yybegin(EXPECT_NON_COMMENT);
return SCRIPT_TEXT;
}
{ScriptText}*{CrLf} { }
{ScriptText}+ {
// EOF met
yybegin(YYINITIAL);
return SCRIPT_TEXT;
}
}

// STATES

[^] { yypushback(yytext().length()); yybegin(EXPECT_NON_COMMENT); }
<YYINITIAL, EXPECT_NON_COMMENT, EXPECT_SCRIPT_ARGUMENTS> {
{WhiteSpace} { return WHITE_SPACE; }
}
<YYINITIAL> {
{WhiteSpaceWithNewLines} { yybegin(YYINITIAL); return WHITE_SPACE;}
{BlockCommentStart} { yybegin(BLOCK_COMMENT_BODY); }
{LineComment} { return LINE_COMMENT; }
[^] { yypushback(yylength()); yybegin(EXPECT_NON_COMMENT); }
}

{WhiteSpaceWithNewLines} { yybegin(YYINITIAL); yypushback(yylength()); return CRLF; }

<EXPECT_NON_COMMENT> {
"{" { return BRACE1; }
"}" { return BRACE2; }
"{}" { yypushback(1); return BRACE1;}
"=" { return EQUALS; }
"->" { return ARROW; }
{Arrow} { return ARROW; }

"!script" { yybegin(EXPECT_SCRIPT_ARGUMENTS); return UNQUOTED_TEXT; }

{QUOTED_TEXT} { return QUOTED_TEXT; }
{UNQUOTED_TEXT} { return UNQUOTED_TEXT; }

{CRLF} { yybegin(YYINITIAL); return CRLF; }
{QuotedText} { return QUOTED_TEXT; }
{UnquotedText} { return UNQUOTED_TEXT; }
}

<EXPECT_SCRIPT_ARGUMENTS> {
"{" { startScript(); return BRACE1; }
{QUOTED_TEXT} { return QUOTED_TEXT; }
{UNQUOTED_TEXT} { return UNQUOTED_TEXT; }
[^] { yybegin(YYINITIAL); yypushback(yytext().length()); }
}

<EXPECT_SCRIPT> {
"{" { braces++; }
"}" {
if (braces == 0) {
endScript();
yypushback(1);
return SCRIPT_TEXT;
}
braces--;
}
{CRLF} { }
{SCRIPT_TEXT} { }
"{" { yybegin(EXPECT_SCRIPT); return BRACE1; }
{QuotedText} { return QUOTED_TEXT; }
{UnquotedText} { return UNQUOTED_TEXT; }
[^] { yybegin(YYINITIAL); yypushback(yylength()); }
}

[^] { return BAD_CHARACTER; }
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nl.dirkgroot.structurizr.dsl.lang

import com.intellij.formatting.*
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiComment
import com.intellij.psi.TokenType.WHITE_SPACE
import com.intellij.psi.formatter.common.AbstractBlock
import com.intellij.psi.tree.TokenSet
Expand Down Expand Up @@ -30,7 +31,7 @@ class SDFormattingBlock(
.toList()

private fun calculateIndent(child: ASTNode) =
if ((child.elementType in INDENT_TOKEN_TYPES || child.psi is SDStatement) &&
if ((child.elementType in INDENT_TOKEN_TYPES || child.psi is SDStatement || child.psi is PsiComment) &&
myNode.treeParent != null && child.psi !is SDRawBlockStatement
)
Indent.getNormalIndent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class StructurizrDSLParserDefinition : ParserDefinition {

override fun getWhitespaceTokens() = WHITE_SPACES

override fun getCommentTokens(): TokenSet = TokenSet.EMPTY
override fun getCommentTokens(): TokenSet = TokenSet.create(SDTypes.LINE_COMMENT, SDTypes.BLOCK_COMMENT)

override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY

Expand Down

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading