Skip to content

Commit d5fa471

Browse files
committed
feat(devin-lang): init basic code fence support #101
1 parent ad4ca23 commit d5fa471

File tree

7 files changed

+84
-23
lines changed

7 files changed

+84
-23
lines changed

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

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,33 +25,51 @@ import com.intellij.psi.TokenType;
2525
%s AGENT_BLOCK
2626
%s VARIABLE_BLOCK
2727
%s COMMAND_BLOCK
28+
%s CODE_BLOCK
2829

2930
IDENTIFIER=[a-zA-Z0-9][_\-a-zA-Z0-9]*
3031
VARIABLE_ID=[a-zA-Z0-9][_\-a-zA-Z0-9]*
3132
AGENT_ID=[a-zA-Z0-9][_\-a-zA-Z0-9]*
3233
COMMAND_ID=[a-zA-Z0-9][_\-a-zA-Z0-9]*
3334
REF_BLOCK=([$/@] {IDENTIFIER} )
3435
TEXT_SEGMENT=[^$/@\n]+
35-
NEWLINE=\n|\r\n
36+
//CODE_CONTENT="```" {IDENTIFIER} ([^$/@\n]+ | \n)* "```"
37+
CODE_CONTENT=([^$/@\n]+ )
38+
NEWLINE= \n | \r | \r\n
3639

3740
%{
38-
private IElementType contextBlock() {
41+
private boolean isCodeStart = false;
42+
%}
43+
44+
%{
45+
private IElementType codeContent() {
3946
yybegin(YYINITIAL);
4047

41-
String text = yytext().toString();
48+
// handle for end which is \n```
49+
String text = yytext().toString().trim();
50+
if (text.equals("\n```") || text.equals("```")) {
51+
isCodeStart = false;
52+
return CODE_BLOCK_END;
53+
}
4254

43-
return TEXT_SEGMENT;
55+
// new line
56+
if (text.equals("\n")) {
57+
return NEWLINE;
58+
}
59+
60+
return CODE_CONTENT;
4461
}
4562
%}
4663

4764
%%
4865
<YYINITIAL> {
49-
"@" { yybegin(AGENT_BLOCK); return AGENT_START; }
50-
"/" { yybegin(COMMAND_BLOCK); return COMMAND_START; }
66+
"@" { yybegin(AGENT_BLOCK); return AGENT_START; }
67+
"/" { yybegin(COMMAND_BLOCK); return COMMAND_START; }
5168
"$" { yybegin(VARIABLE_BLOCK); return VARIABLE_START; }
69+
"```" {IDENTIFIER} { yybegin(CODE_BLOCK); isCodeStart = true; return CODE_BLOCK_START; }
5270

53-
{TEXT_SEGMENT} { return TEXT_SEGMENT; }
54-
{NEWLINE} { return NEWLINE; }
71+
{TEXT_SEGMENT} { if(isCodeStart) { return codeContent(); } else { return TEXT_SEGMENT; } }
72+
{NEWLINE} { return NEWLINE; }
5573
[^] { return TokenType.BAD_CHARACTER; }
5674
}
5775

@@ -69,3 +87,9 @@ NEWLINE=\n|\r\n
6987
{VARIABLE_ID} { yybegin(YYINITIAL); return VARIABLE_ID; }
7088
[^] { return TokenType.BAD_CHARACTER; }
7189
}
90+
91+
<CODE_BLOCK> {
92+
{CODE_CONTENT} { return codeContent(); }
93+
<<EOF>> { isCodeStart = false; return codeContent(); }
94+
[^] { }
95+
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
tokenTypeClass="cc.unitmesh.language.lexer.DevInTokenType"
1616

1717
tokens=[
18-
AGENT_START = "AGENT_START"
19-
COMMAND_START = "COMMAND_START"
20-
VARIABLE_START = "VARIABLE_START"
21-
IDENTIFIER = "IDENTIFIER"
18+
AGENT_START = "AGENT_START"
19+
COMMAND_START = "COMMAND_START"
20+
VARIABLE_START = "VARIABLE_START"
21+
CODE_BLOCK_START = "CODE_BLOCK_START"
22+
CODE_BLOCK_END = "CODE_BLOCK_END"
23+
CODE_BLOCK = "CODE_BLOCK"
24+
CODE_CONTENT = "CODE_CONTENT"
25+
IDENTIFIER = "IDENTIFIER"
2226
]
2327
}
2428

@@ -31,5 +35,5 @@ used ::= (
3135
)
3236

3337
code ::= (
34-
"```" IDENTIFIER TEXT_SEGMENT "```"
38+
CODE_BLOCK_START (NEWLINE | CODE_CONTENT)* CODE_BLOCK_END
3539
)

exts/devin-lang/src/test/kotlin/cc/unitmesh/language/DevInParsingTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ class DevInParsingTest : ParsingTestCase("parser", "devin", DevInParserDefinitio
1414
fun testJavaHelloWorld() {
1515
doTest(true)
1616
}
17-
}
17+
18+
fun testEmptyCodeFence() {
19+
doTest(true)
20+
}
21+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
解释如下的代码:
2+
3+
```
4+
print("Hello, world!")
5+
```
6+
7+
请使用 Markdown 语法返回。
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
DevInFile
2+
PsiElement(DevInTokenType.TEXT_SEGMENT)('解释如下的代码:')
3+
PsiElement(DevInTokenType.NEWLINE)('\n')
4+
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)('```')
10+
PsiElement(DevInTokenType.NEWLINE)('\n')
11+
PsiElement(DevInTokenType.NEWLINE)('\n')
12+
PsiElement(DevInTokenType.TEXT_SEGMENT)('请使用 Markdown 语法返回。')
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
解释如下的代码:
2+
13
```java
24
public class Main {
35
public static void main(String[] args) {
46
System.out.println("Hello, world!");
57
}
68
}
79
```
10+
11+
请使用 Markdown 语法返回。
Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
DevInFile
2-
PsiElement(DevInTokenType.TEXT_SEGMENT)('```java')
2+
PsiElement(DevInTokenType.TEXT_SEGMENT)('解释如下的代码:')
33
PsiElement(DevInTokenType.NEWLINE)('\n')
4-
PsiElement(DevInTokenType.TEXT_SEGMENT)('public class Main {')
54
PsiElement(DevInTokenType.NEWLINE)('\n')
6-
PsiElement(DevInTokenType.TEXT_SEGMENT)(' public static void main(String[] args) {')
5+
DevInCodeImpl(CODE)
6+
PsiElement(DevInTokenType.CODE_BLOCK_START)('```java')
7+
PsiElement(DevInTokenType.CODE_CONTENT)('\npublic class Main {')
8+
PsiElement(DevInTokenType.NEWLINE)('\n')
9+
PsiElement(DevInTokenType.CODE_CONTENT)(' public static void main(String[] args) {')
10+
PsiElement(DevInTokenType.NEWLINE)('\n')
11+
PsiElement(DevInTokenType.CODE_CONTENT)(' System.out.println("Hello, world!");')
12+
PsiElement(DevInTokenType.NEWLINE)('\n')
13+
PsiElement(DevInTokenType.CODE_CONTENT)(' }')
14+
PsiElement(DevInTokenType.NEWLINE)('\n')
15+
PsiElement(DevInTokenType.CODE_CONTENT)('}')
16+
PsiElement(DevInTokenType.NEWLINE)('\n')
17+
PsiElement(DevInTokenType.CODE_BLOCK_END)('```')
718
PsiElement(DevInTokenType.NEWLINE)('\n')
8-
PsiElement(DevInTokenType.TEXT_SEGMENT)(' System.out.println("Hello, world!");')
919
PsiElement(DevInTokenType.NEWLINE)('\n')
10-
PsiElement(DevInTokenType.TEXT_SEGMENT)(' }')
11-
PsiElement(DevInTokenType.NEWLINE)('\n')
12-
PsiElement(DevInTokenType.TEXT_SEGMENT)('}')
13-
PsiElement(DevInTokenType.NEWLINE)('\n')
14-
PsiElement(DevInTokenType.TEXT_SEGMENT)('```')
20+
PsiElement(DevInTokenType.TEXT_SEGMENT)('请使用 Markdown 语法返回。')

0 commit comments

Comments
 (0)