Skip to content

Commit 81ebee4

Browse files
committed
feat(devin-lang): update language grammar and lexer to support optional language identifiers in code blocks. #101
1 parent ca35bca commit 81ebee4

File tree

3 files changed

+17
-13
lines changed

3 files changed

+17
-13
lines changed

exts/devin-lang/src/grammar/DevInLexer.flex

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ NEWLINE= \n | \r | \r\n
4949

5050
// handle for end which is \n```
5151
String text = yytext().toString().trim();
52-
if (text.equals("\n```") || text.equals("```")) {
52+
if ((text.equals("\n```") || text.equals("```")) && isCodeStart == true ) {
5353
isCodeStart = false;
5454
return CODE_BLOCK_END;
5555
}
@@ -59,6 +59,10 @@ NEWLINE= \n | \r | \r\n
5959
return NEWLINE;
6060
}
6161

62+
if (isCodeStart == false) {
63+
return TEXT_SEGMENT;
64+
}
65+
6266
return CODE_CONTENT;
6367
}
6468
%}
@@ -68,7 +72,7 @@ NEWLINE= \n | \r | \r\n
6872
"@" { yybegin(AGENT_BLOCK); return AGENT_START; }
6973
"/" { yybegin(COMMAND_BLOCK); return COMMAND_START; }
7074
"$" { yybegin(VARIABLE_BLOCK); return VARIABLE_START; }
71-
"```" {IDENTIFIER} { yybegin(LANG_ID); isCodeStart = true; yypushback(yylength()); }
75+
"```" {IDENTIFIER}? { yybegin(LANG_ID); if (isCodeStart == true) { isCodeStart = false; return CODE_BLOCK_END; } else { isCodeStart = true; }; yypushback(yylength()); }
7276

7377
{TEXT_SEGMENT} { if(isCodeStart) { return codeContent(); } else { return TEXT_SEGMENT; } }
7478
{NEWLINE} { return NEWLINE; }
@@ -91,10 +95,10 @@ NEWLINE= \n | \r | \r\n
9195
}
9296

9397
<CODE_BLOCK> {
94-
{CODE_CONTENT} { return codeContent(); }
98+
{CODE_CONTENT} { if(isCodeStart) { return codeContent(); } else { yybegin(YYINITIAL); yypushback(yylength()); } }
9599
{NEWLINE} { return NEWLINE; }
96-
<<EOF>> { isCodeStart = false; return codeContent(); }
97-
[^] { }
100+
<<EOF>> { isCodeStart = false; yybegin(YYINITIAL); yypushback(yylength()); }
101+
[^] { isCodeStart = false; yybegin(YYINITIAL); yypushback(yylength()); }
98102
}
99103

100104
<LANG_ID> {

exts/devin-lang/src/grammar/DevInParser.bnf

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ used ::= (
3535
| VARIABLE_START VARIABLE_ID?
3636
)
3737

38-
code ::= (
39-
CODE_BLOCK_START LANGUAGE_ID code_contents CODE_BLOCK_END
40-
)
38+
code ::= CODE_BLOCK_START LANGUAGE_ID? code_contents CODE_BLOCK_END
4139

4240
code_contents ::= (NEWLINE | CODE_CONTENT)*

exts/devin-lang/src/test/testData/parser/EmptyCodeFence.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ DevInFile
22
PsiElement(DevInTokenType.TEXT_SEGMENT)('解释如下的代码:')
33
PsiElement(DevInTokenType.NEWLINE)('\n')
44
PsiElement(DevInTokenType.NEWLINE)('\n')
5-
PsiElement(DevInTokenType.TEXT_SEGMENT)('```')
6-
PsiElement(DevInTokenType.NEWLINE)('\n')
7-
PsiElement(DevInTokenType.TEXT_SEGMENT)('print("Hello, world!")')
8-
PsiElement(DevInTokenType.NEWLINE)('\n')
9-
PsiElement(DevInTokenType.TEXT_SEGMENT)('```')
5+
DevInCodeImpl(CODE)
6+
PsiElement(DevInTokenType.CODE_BLOCK_START)('```')
7+
DevInCodeContentsImpl(CODE_CONTENTS)
8+
PsiElement(DevInTokenType.NEWLINE)('\n')
9+
PsiElement(DevInTokenType.CODE_CONTENT)('print("Hello, world!")')
10+
PsiElement(DevInTokenType.NEWLINE)('\n')
11+
PsiElement(DevInTokenType.CODE_BLOCK_END)('```')
1012
PsiElement(DevInTokenType.NEWLINE)('\n')
1113
PsiElement(DevInTokenType.NEWLINE)('\n')
1214
PsiElement(DevInTokenType.TEXT_SEGMENT)('请使用 Markdown 语法返回。')

0 commit comments

Comments
 (0)