From 8750e3869b2b8c9c42da069ad9d43eaeae848c7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A0=95=ED=95=9C=20Rycont?=
<35295182+rycont@users.noreply.github.com>
Date: Wed, 18 Dec 2024 11:54:06 +0000
Subject: [PATCH 01/20] feat: implement basic level tokenizer(syntax highlight)
---
docs/_/code-runner.vue | 99 ++++++++++++++++++++++++++++++++++++++----
docs/_/create-docs.ts | 2 +-
2 files changed, 92 insertions(+), 9 deletions(-)
diff --git a/docs/_/code-runner.vue b/docs/_/code-runner.vue
index 8184ed9..86674ec 100644
--- a/docs/_/code-runner.vue
+++ b/docs/_/code-runner.vue
@@ -1,7 +1,8 @@
-
-
# 약속 (함수)
::: tip
@@ -17,7 +13,7 @@ import CodeRunner from "../_/code-runner.vue"
약속을 정의할 때는 `약속` 키워드로 시작하며, 다음과 같은 형식으로 만듭니다:
-
@@ -33,7 +29,7 @@ import CodeRunner from "../_/code-runner.vue"
약속은 여러 개의 매개변수를 가질 수 있습니다.
-
@@ -42,19 +38,19 @@ import CodeRunner from "../_/code-runner.vue"
한국어에는 단어 마지막 음절의 받침 유무에 따라 어울리는 조사가 달라집니다. 그렇기에, 약속을 정의할 때 다음과 같은 어색한 표현을 만날 수 있습니다.
-
한국어에서 '재혁'이라는 단어에 어울리는 목적격 조사는 '을'이지만, 약속이 '를'로 정의되었기 때문에 코드가 어색해 보입니다. 이러한 경우를 피하기 위해 약속을 정의할 때 조사 변형을 반영할 수 있습니다.
-
약속을 정의할 때 `/`를 사이에 두고 여러 조사를 작성하면 됩니다. 한글자 조사 뿐만 아니라, 다음과 같은 경우도 가능합니다.
-
@@ -69,7 +65,7 @@ import CodeRunner from "../_/code-runner.vue"
직접 정의한 약속을 사용해 **섭씨 25도를 화씨로 변환해보세요.**
-
-import CodeRunner from "../_/code-runner.vue"
const challenge = {
output: "100",
@@ -19,4 +18,4 @@ const challenge = {
`100`을 보여주는 코드를 작성해보세요.
-
+
diff --git "a/docs/language/3. \354\210\253\354\236\220\354\231\200 \354\227\260\354\202\260.md" "b/docs/language/3. \354\210\253\354\236\220\354\231\200 \354\227\260\354\202\260.md"
index 8353fbe..8d01056 100644
--- "a/docs/language/3. \354\210\253\354\236\220\354\231\200 \354\227\260\354\202\260.md"
+++ "b/docs/language/3. \354\210\253\354\236\220\354\231\200 \354\227\260\354\202\260.md"
@@ -1,5 +1,4 @@
-
# 변수
변수는 **값을 저장하는 공간**입니다. 값에 이름을 붙혀 저장하고 나중에 다시 사용할 수 있습니다.
@@ -15,7 +11,7 @@ import CodeRunner from "../_/code-runner.vue"
- 의미있는 이름으로 값을 표현할 때
- 계산 결과를 저장할 때
-
### 계산에서 변수 활용하기
-
@@ -63,7 +59,7 @@ import CodeRunner from "../_/code-runner.vue"
변수를 사용하여 섭씨온도 **10도**를 화씨온도로 변환해서 보여주세요. 섭씨온도를 화씨온도로 바꾸려면 9를 곱하고 5로 나누고 32를 더하면 됩니다.
-
-import CodeRunner from "../_/code-runner.vue"
-
-
# 문자
::: tip
@@ -10,32 +6,32 @@ import CodeRunner from "../_/code-runner.vue"
약속에서는 숫자뿐만 아니라 문자도 다룰 수 있습니다. 문자를 표현하려면 따옴표 안에 글을 작성하면 됩니다. 큰 따옴표(`"`)와 작은 따옴표(`'`)를 사용할 수 있습니다.
-
+
## 문자 이어붙이기
덧셈 기호(`+`)를 사용해 문자를 이어붙일 수 있습니다.
-
문자와 숫자도 함께 이어붙일 수 있습니다.
-
변수에 저장하지 않고 문자를 직접 사용할 수도 있습니다.
-
+
::: tip 단어 사이 띄어쓰기
문자를 이어붙일 때 단어 사이에 띄어쓰기를 넣으려면 공백 문자(" ")를 포함해야 합니다.
-
:::
@@ -44,13 +40,13 @@ import CodeRunner from "../_/code-runner.vue"
곱셈 기호를 사용해 문자를 반복할 수 있습니다.
-
+
## 직접 해보기
영희의 이름과 나이가 변수에 저장되어 있습니다. **"제 이름은 영희이고, 12살입니다."** 를 보여주는 코드를 작성해보세요.
-
-import CodeRunner from "../_/code-runner.vue"
-
-
# 목록
약속에서는 여러 개의 값을 하나로 묶어서 저장할 수 있습니다. 이를 **목록**이라고 부릅니다.
@@ -10,14 +6,14 @@ import CodeRunner from "../_/code-runner.vue"
목록은 대괄호(`[` `]`) 안에 값들을 쉼표(`,`)로 구분하여 만듭니다.
-
## 목록의 값 가져오기
목록의 특정 위치에 있는 값을 가져오려면 대괄호 안에 위치 번호를 적으면 됩니다.
-
@@ -25,7 +21,7 @@ import CodeRunner from "../_/code-runner.vue"
변수와 동일한 문법을 사용하여 목록의 내용을 바꿉니다.
-
@@ -33,7 +29,7 @@ import CodeRunner from "../_/code-runner.vue"
여러 위치의 값을 한번에 가져오려면 대괄호 안에 목록을 넣으면 됩니다. 이 경우 새로운 목록이 만들어집니다.
-
@@ -41,7 +37,7 @@ import CodeRunner from "../_/code-runner.vue"
좋아하는 과일들이 담긴 목록이 있습니다. 두 번째 과일을 "배"로 바꾸고 전체 목록을 출력해보세요.
-
-import CodeRunner from "../_/code-runner.vue"
-
-
# 조건문
조건문은 **주어진 조건에 따라 다른 동작을 실행**하는 구문입니다. 특정 조건이 참일 때와 거짓일 때 서로 다른 코드를 실행할 수 있습니다.
@@ -48,7 +44,7 @@ import CodeRunner from "../_/code-runner.vue"
## 조건문 사용하기
- 80 이면
"합격" 보여주기
"축하드립니다!" 보여주기' />
@@ -57,7 +53,7 @@ import CodeRunner from "../_/code-runner.vue"
조건문이 거짓일 때 실행할 코드는 `아니면`을 사용해 작성합니다.
- 80 이면
"합격" 보여주기
"축하드립니다!" 보여주기
@@ -70,7 +66,7 @@ import CodeRunner from "../_/code-runner.vue"
둘 이상의 조건을 가늠할 때는 `만약`, `아니면 만약`, `아니면`을 사용해 다중 조건문을 작성할 수 있습니다.
-= 90 이면
그레이드: "A"
@@ -86,7 +82,7 @@ import CodeRunner from "../_/code-runner.vue"
조건문 본문 안에서도 조건문을 또 작성할 수 있습니다. 이 경우를 겹친 조건문이라고 합니다.
-= 80 이면
만약 실기시험_점수 >= 80 이면
@@ -108,7 +104,7 @@ import CodeRunner from "../_/code-runner.vue"
지혜가 해낸 팔굽혀펴기 개수가 변수에 저장되어 있습니다. **"지혜의 팔굽혀펴기 등급은 [등급]입니다."** 를 보여주는 코드를 작성해보세요.
-
-import CodeRunner from "../_/code-runner.vue"
-
-
# 논리 연산자
여러 개의 참/거짓을 비교할 때는 논리 연산자를 사용합니다. 이를 사용해 복잡한 조건문을 만들 수 있습니다.
@@ -14,7 +10,7 @@ import CodeRunner from "../_/code-runner.vue"
`이고` 또는 `그리고` 연산자는 **두 조건이 모두 참일 때**만 참이 됩니다.
- 80 이고 재현_영어점수 > 80\n
만약 재현_통과 이면
@@ -28,7 +24,7 @@ import CodeRunner from "../_/code-runner.vue"
`이거나` 또는 `거나` 연산자는 두 조건 중 하나라도 참이면 참이 됩니다.
- 80 이고 영어점수 > 80
@@ -63,7 +59,7 @@ import CodeRunner from "../_/code-runner.vue"
합격했다면 "합격", 아니면 "불합격"을 출력하는 코드를 작성해보세요.
-
-import CodeRunner from "../_/code-runner.vue"
-
-
# 반복문
반복문은 **특정 코드를 여러 번 실행**하는 구문입니다. 동일한 작업을 반복해야 할 때 유용합니다.
@@ -14,7 +10,7 @@ import CodeRunner from "../_/code-runner.vue"
종료 조건을 설정하지 않으면 무한 반복되어 프로그램이나 컴퓨터에 과부하가 걸립니다. 종료 조건을 설정하는 것을 잊지 마세요.
:::
-
@@ -33,7 +29,7 @@ import CodeRunner from "../_/code-runner.vue"
1부터 10까지의 숫자 중 짝수만 출력하는 코드를 작성해보세요.
-
Date: Sun, 22 Dec 2024 10:41:53 +0000
Subject: [PATCH 09/20] feat: ignore unknown tokens during token to node
conversion
---
core/prepare/lex/convert-tokens-to-nodes.ts | 29 ++++++--------
deno.json | 3 +-
deno.lock | 6 +++
docs/_/code-runner/index.vue | 4 +-
docs/_/code-runner/merge-syntax.ts | 39 -------------------
.../ast-to-colorize/declare-function.ts | 0
.../ast-to-colorize/get-comment-color-part.ts | 0
.../ast-to-colorize/index.ts | 0
.../ast-to-colorize/scope.ts | 0
monaco-language-provider/deno.json | 7 ++++
monaco-language-provider/mod.ts | 1 +
.../tokenize-provider.ts | 5 ++-
.../type.ts | 0
13 files changed, 32 insertions(+), 62 deletions(-)
delete mode 100644 docs/_/code-runner/merge-syntax.ts
rename {docs/_/code-runner => monaco-language-provider}/ast-to-colorize/declare-function.ts (100%)
rename {docs/_/code-runner => monaco-language-provider}/ast-to-colorize/get-comment-color-part.ts (100%)
rename {docs/_/code-runner => monaco-language-provider}/ast-to-colorize/index.ts (100%)
rename {docs/_/code-runner => monaco-language-provider}/ast-to-colorize/scope.ts (100%)
create mode 100644 monaco-language-provider/deno.json
create mode 100644 monaco-language-provider/mod.ts
rename {docs/_/code-runner => monaco-language-provider}/tokenize-provider.ts (94%)
rename {docs/_/code-runner => monaco-language-provider}/type.ts (100%)
diff --git a/core/prepare/lex/convert-tokens-to-nodes.ts b/core/prepare/lex/convert-tokens-to-nodes.ts
index 9e710d1..febca62 100644
--- a/core/prepare/lex/convert-tokens-to-nodes.ts
+++ b/core/prepare/lex/convert-tokens-to-nodes.ts
@@ -12,39 +12,32 @@ export function convertTokensToNodes(tokens: Token[]): Node[] {
function mapTokenToNode(token: Token) {
switch (token.type) {
+ case TOKEN_TYPE.SPACE:
+ case TOKEN_TYPE.LINE_COMMENT:
+ case TOKEN_TYPE.UNKNOWN:
+ return null
+ case TOKEN_TYPE.COMMA:
+ case TOKEN_TYPE.OPENING_PARENTHESIS:
+ case TOKEN_TYPE.CLOSING_PARENTHESIS:
+ case TOKEN_TYPE.OPENING_BRACKET:
+ case TOKEN_TYPE.CLOSING_BRACKET:
+ case TOKEN_TYPE.COLON:
+ return new Expression(token.value, [token])
case TOKEN_TYPE.NUMBER:
return new NumberLiteral(parseFloat(token.value), [token])
case TOKEN_TYPE.STRING:
return new StringLiteral(token.value.slice(1, -1), [token])
case TOKEN_TYPE.OPERATOR:
return new Operator(token.value, [token])
- case TOKEN_TYPE.SPACE:
- return null
case TOKEN_TYPE.INDENT:
return new Indent(token.value.length, [token])
case TOKEN_TYPE.IDENTIFIER:
return new Identifier(token.value, [token])
- case TOKEN_TYPE.COMMA:
- case TOKEN_TYPE.OPENING_PARENTHESIS:
- case TOKEN_TYPE.CLOSING_PARENTHESIS:
- case TOKEN_TYPE.OPENING_BRACKET:
- case TOKEN_TYPE.CLOSING_BRACKET:
- case TOKEN_TYPE.COLON:
- return new Expression(token.value, [token])
case TOKEN_TYPE.FFI_BODY:
return new FFIBody(token.value.slice(3, -3), [token])
case TOKEN_TYPE.NEW_LINE:
return new EOL([token])
- case TOKEN_TYPE.LINE_COMMENT:
- return null
case TOKEN_TYPE.MENTION:
return new Mention(token.value.slice(1), [token])
- case TOKEN_TYPE.UNKNOWN:
- throw new UnexpectedCharError({
- resource: {
- parts: '코드',
- char: token.value,
- },
- })
}
}
diff --git a/deno.json b/deno.json
index 016819f..151ddf1 100644
--- a/deno.json
+++ b/deno.json
@@ -19,7 +19,8 @@
"quickjs",
"docs",
"core",
- "test"
+ "test",
+ "monaco-language-provider"
],
"version": "0.2.0-alpha.11+20241217.nightly",
"tasks": {
diff --git a/deno.lock b/deno.lock
index a4351d9..104aed8 100644
--- a/deno.lock
+++ b/deno.lock
@@ -10,6 +10,7 @@
"npm:ansi-to-html@~0.7.2": "0.7.2",
"npm:madge@*": "8.0.0",
"npm:monaco-editor@0.52": "0.52.2",
+ "npm:monaco-editor@~0.52.2": "0.52.2",
"npm:quickjs-emscripten-core@0.31": "0.31.0",
"npm:quickjs-emscripten@0.31": "0.31.0",
"npm:typedoc-plugin-markdown@^4.2.10": "4.3.2_typedoc@0.27.4__typescript@5.6.3",
@@ -2188,6 +2189,11 @@
"npm:vue@^3.5.12"
]
},
+ "monaco-language-provider": {
+ "dependencies": [
+ "npm:monaco-editor@~0.52.2"
+ ]
+ },
"quickjs": {
"dependencies": [
"npm:quickjs-emscripten-core@0.31",
diff --git a/docs/_/code-runner/index.vue b/docs/_/code-runner/index.vue
index 0aaa7d3..dcb04c1 100644
--- a/docs/_/code-runner/index.vue
+++ b/docs/_/code-runner/index.vue
@@ -4,7 +4,7 @@ import AnsiCode from 'ansi-to-html'
import type { editor, languages } from 'monaco-editor'
import { yaksok, tokenize } from '@dalbit-yaksok/core'
-import { TokenizeProvider } from './tokenize-provider'
+import { MonacoDalbitYaksokProvider } from '@dalbit-yaksok/monaco-language-provider'
const props = defineProps({
code: {
@@ -39,7 +39,7 @@ async function initializeMonaco() {
languages.register({ id: 'yaksok' })
- const tokenizeProvider = new TokenizeProvider(code.value)
+ const tokenizeProvider = new MonacoDalbitYaksokProvider(code.value)
languages.onLanguage('yaksok', () => {
languages.setLanguageConfiguration('yaksok', {
diff --git a/docs/_/code-runner/merge-syntax.ts b/docs/_/code-runner/merge-syntax.ts
deleted file mode 100644
index f5ba43f..0000000
--- a/docs/_/code-runner/merge-syntax.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { TOKEN_TYPE } from '@dalbit-yaksok/core'
-import { ColorToken } from './type.ts'
-
-export function mergeSyntax(_tokens: ColorToken[]) {
- const tokens = _tokens.slice()
- mergeVariableDeclaration(tokens)
-
- return tokens
-}
-
-function mergeVariableDeclaration(tokens: ColorToken[]) {
- const colonPositions: number[] = []
-
- for (const index in tokens) {
- const current = tokens[index]
-
- if (current.type === TOKEN_TYPE.COLON) {
- colonPositions.push(+index)
- }
- }
-
- for (const colonPosition of colonPositions) {
- for (
- let i = colonPosition;
- tokens[i] &&
- tokens[i].type !== TOKEN_TYPE.NEW_LINE &&
- tokens[i].type !== TOKEN_TYPE.INDENT;
- i--
- ) {
- if (tokens[i].type === TOKEN_TYPE.IDENTIFIER) {
- if (tokens[i].value === '결과') {
- tokens[i].scope = 'keyword'
- } else {
- tokens[i].scope = 'variable'
- }
- }
- }
- }
-}
diff --git a/docs/_/code-runner/ast-to-colorize/declare-function.ts b/monaco-language-provider/ast-to-colorize/declare-function.ts
similarity index 100%
rename from docs/_/code-runner/ast-to-colorize/declare-function.ts
rename to monaco-language-provider/ast-to-colorize/declare-function.ts
diff --git a/docs/_/code-runner/ast-to-colorize/get-comment-color-part.ts b/monaco-language-provider/ast-to-colorize/get-comment-color-part.ts
similarity index 100%
rename from docs/_/code-runner/ast-to-colorize/get-comment-color-part.ts
rename to monaco-language-provider/ast-to-colorize/get-comment-color-part.ts
diff --git a/docs/_/code-runner/ast-to-colorize/index.ts b/monaco-language-provider/ast-to-colorize/index.ts
similarity index 100%
rename from docs/_/code-runner/ast-to-colorize/index.ts
rename to monaco-language-provider/ast-to-colorize/index.ts
diff --git a/docs/_/code-runner/ast-to-colorize/scope.ts b/monaco-language-provider/ast-to-colorize/scope.ts
similarity index 100%
rename from docs/_/code-runner/ast-to-colorize/scope.ts
rename to monaco-language-provider/ast-to-colorize/scope.ts
diff --git a/monaco-language-provider/deno.json b/monaco-language-provider/deno.json
new file mode 100644
index 0000000..967fa25
--- /dev/null
+++ b/monaco-language-provider/deno.json
@@ -0,0 +1,7 @@
+{
+ "imports": {
+ "monaco-editor": "npm:monaco-editor@^0.52.2"
+ },
+ "name": "@dalbit-yaksok/monaco-language-provider",
+ "exports": "./mod.ts"
+}
\ No newline at end of file
diff --git a/monaco-language-provider/mod.ts b/monaco-language-provider/mod.ts
new file mode 100644
index 0000000..a464324
--- /dev/null
+++ b/monaco-language-provider/mod.ts
@@ -0,0 +1 @@
+export { MonacoDalbitYaksokProvider } from './tokenize-provider.ts'
diff --git a/docs/_/code-runner/tokenize-provider.ts b/monaco-language-provider/tokenize-provider.ts
similarity index 94%
rename from docs/_/code-runner/tokenize-provider.ts
rename to monaco-language-provider/tokenize-provider.ts
index 7c9b00c..9fc107d 100644
--- a/docs/_/code-runner/tokenize-provider.ts
+++ b/monaco-language-provider/tokenize-provider.ts
@@ -1,11 +1,11 @@
import type { languages } from 'monaco-editor'
import { parse, CodeFile } from '@dalbit-yaksok/core'
-import { ColorPart } from './type.ts'
import { nodeToColorTokens } from './ast-to-colorize/index.ts'
import { getCommentColorParts } from './ast-to-colorize/get-comment-color-part.ts'
+import { ColorPart } from './type.ts'
-export class TokenizeProvider implements languages.TokensProvider {
+export class MonacoDalbitYaksokProvider implements languages.TokensProvider {
private colorPartsByLine: Map
private lines: string[]
@@ -55,6 +55,7 @@ export class TokenizeProvider implements languages.TokensProvider {
tokenize(line: string, state: any) {
const lineNumber = this.lines.indexOf(line)
+ console.log(lineNumber)
const colorParts = this.colorPartsByLine
.get(lineNumber)!
.map((part) => ({
diff --git a/docs/_/code-runner/type.ts b/monaco-language-provider/type.ts
similarity index 100%
rename from docs/_/code-runner/type.ts
rename to monaco-language-provider/type.ts
From 2ca1e2110e907cb581e7e91675b7aec1f56562e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A0=95=ED=95=9C=20Rycont?=
<35295182+rycont@users.noreply.github.com>
Date: Sun, 22 Dec 2024 10:44:07 +0000
Subject: [PATCH 10/20] test: remove invalid character error check during
parsing
---
test/errors/invalid-character-for-code.test.ts | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 test/errors/invalid-character-for-code.test.ts
diff --git a/test/errors/invalid-character-for-code.test.ts b/test/errors/invalid-character-for-code.test.ts
deleted file mode 100644
index 645b77b..0000000
--- a/test/errors/invalid-character-for-code.test.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { assertIsError, unreachable } from 'assert'
-import { yaksok } from '../../core/mod.ts'
-import { UnexpectedCharError } from '../../core/error/index.ts'
-
-Deno.test('사용할 수 없는 문자', async () => {
- try {
- await yaksok(`내 이름: "정한";`)
- unreachable()
- } catch (error) {
- assertIsError(error, UnexpectedCharError)
- }
-})
From 20e65a5e285edab171042f72867538555a61da77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A0=95=ED=95=9C=20Rycont?=
<35295182+rycont@users.noreply.github.com>
Date: Sun, 22 Dec 2024 11:21:56 +0000
Subject: [PATCH 11/20] feat: support list loop highlighting
---
core/node/index.ts | 1 +
docs/index.md | 20 +++---
.../ast-to-colorize/index.ts | 58 +++++++++++++++++
.../ast-to-colorize/list-loop.ts | 62 +++++++++++++++++++
4 files changed, 133 insertions(+), 8 deletions(-)
create mode 100644 monaco-language-provider/ast-to-colorize/list-loop.ts
diff --git a/core/node/index.ts b/core/node/index.ts
index 3f1b2a6..5802975 100644
--- a/core/node/index.ts
+++ b/core/node/index.ts
@@ -12,3 +12,4 @@ export * from './variable.ts'
export * from './return.ts'
export * from './mention.ts'
export * from './ffi.ts'
+export * from './listLoop.ts'
diff --git a/docs/index.md b/docs/index.md
index eea4849..2122e9f 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -30,14 +30,18 @@ features:
diff --git a/monaco-language-provider/ast-to-colorize/index.ts b/monaco-language-provider/ast-to-colorize/index.ts
index 82a5dd4..f15da8a 100644
--- a/monaco-language-provider/ast-to-colorize/index.ts
+++ b/monaco-language-provider/ast-to-colorize/index.ts
@@ -4,6 +4,8 @@ import {
Formula,
FunctionInvoke,
Identifier,
+ IfStatement,
+ ListLoop,
Node,
NumberLiteral,
Operator,
@@ -16,6 +18,7 @@ import {
import { ColorPart } from '../type.ts'
import { SCOPE } from './scope.ts'
import { parseFunctionDeclareHeader } from './declare-function.ts'
+import { parseListLoopHeader } from './list-loop.ts'
function node(node: Node): ColorPart[] {
if (node instanceof Block) {
@@ -62,6 +65,14 @@ function node(node: Node): ColorPart[] {
return stringLiteral(node)
}
+ if (node instanceof IfStatement) {
+ return ifStatement(node)
+ }
+
+ if (node instanceof ListLoop) {
+ return listLoop(node)
+ }
+
console.log('Unknown node:', node)
return []
@@ -217,4 +228,51 @@ function stringLiteral(current: StringLiteral): ColorPart[] {
]
}
+function ifStatement(current: IfStatement): ColorPart[] {
+ let colorParts: ColorPart[] = [
+ {
+ position: current.tokens[0].position,
+ scopes: SCOPE.KEYWORD,
+ },
+ ]
+
+ const newLineIndex = current.tokens.findIndex(
+ (token) => token.type === TOKEN_TYPE.NEW_LINE,
+ )
+
+ const ifStatementHeaderEnder: ColorPart = {
+ position: current.tokens[newLineIndex - 1].position,
+ scopes: SCOPE.KEYWORD,
+ }
+
+ colorParts.push(ifStatementHeaderEnder)
+
+ for (const caseBlock of current.cases) {
+ if (caseBlock.condition) {
+ colorParts = colorParts.concat(node(caseBlock.condition))
+ }
+
+ colorParts = colorParts.concat(block(caseBlock.body))
+ }
+
+ colorParts = colorParts.toSorted(
+ (a, b) => a.position.column - b.position.column,
+ )
+
+ return colorParts
+}
+
+function listLoop(current: ListLoop): ColorPart[] {
+ let colorParts = parseListLoopHeader(current)
+
+ colorParts = colorParts.concat(node(current.list))
+ colorParts = colorParts.concat(block(current.body))
+
+ colorParts = colorParts.toSorted(
+ (a, b) => a.position.column - b.position.column,
+ )
+
+ return colorParts
+}
+
export { node as nodeToColorTokens }
diff --git a/monaco-language-provider/ast-to-colorize/list-loop.ts b/monaco-language-provider/ast-to-colorize/list-loop.ts
new file mode 100644
index 0000000..59f4c74
--- /dev/null
+++ b/monaco-language-provider/ast-to-colorize/list-loop.ts
@@ -0,0 +1,62 @@
+import { ListLoop, TOKEN_TYPE } from '@dalbit-yaksok/core'
+import { ColorPart } from '../type.ts'
+import { SCOPE } from './scope.ts'
+
+export function parseListLoopHeader(node: ListLoop) {
+ let colorParts: ColorPart[] = [
+ {
+ position: node.tokens[0].position,
+ scopes: SCOPE.KEYWORD,
+ },
+ ]
+
+ const newLineIndex = node.tokens.findIndex(
+ (token) => token.type === TOKEN_TYPE.NEW_LINE,
+ )
+
+ const listLoopHeaderTokens = node.tokens.slice(1, newLineIndex)
+
+ const listLoopHeaderEnder: ColorPart = {
+ position:
+ listLoopHeaderTokens[listLoopHeaderTokens.length - 1].position,
+ scopes: SCOPE.KEYWORD,
+ }
+
+ colorParts.push(listLoopHeaderEnder)
+
+ const indexVariableName = node.variableName
+
+ const variableNameToken = listLoopHeaderTokens.find(
+ (token) => token.value === indexVariableName,
+ )
+
+ if (variableNameToken) {
+ const variableNameColorPart: ColorPart = {
+ position: variableNameToken.position,
+ scopes: SCOPE.VARIABLE_NAME,
+ }
+
+ colorParts.push(variableNameColorPart)
+ }
+
+ const listEndingToken = node.list.tokens?.[node.list.tokens.length - 1]
+ if (listEndingToken) {
+ const listEndingTokenIndex =
+ listLoopHeaderTokens.indexOf(listEndingToken)
+
+ const afterListIdentifier = listLoopHeaderTokens
+ .slice(listEndingTokenIndex + 1)
+ .find((token) => token.type === TOKEN_TYPE.IDENTIFIER)
+
+ if (afterListIdentifier && afterListIdentifier.value === '의') {
+ const inKeywordIdentifier: ColorPart = {
+ position: afterListIdentifier.position,
+ scopes: SCOPE.KEYWORD,
+ }
+
+ colorParts.push(inKeywordIdentifier)
+ }
+ }
+
+ return colorParts
+}
From 4db4fcb12ec9e45c620ad47a9616e1cc155ca610 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A0=95=ED=95=9C=20Rycont?=
<35295182+rycont@users.noreply.github.com>
Date: Sun, 22 Dec 2024 11:31:53 +0000
Subject: [PATCH 12/20] feat: support list literal syntax highlighting
---
core/node/list.ts | 4 +-
docs/index.md | 13 +--
.../ast-to-colorize/index.ts | 79 +++++++++++++++++++
.../ast-to-colorize/list-loop.ts | 2 +-
4 files changed, 84 insertions(+), 14 deletions(-)
diff --git a/core/node/list.ts b/core/node/list.ts
index a6bafde..2a90360 100644
--- a/core/node/list.ts
+++ b/core/node/list.ts
@@ -111,8 +111,8 @@ export class SetToIndex extends Executable {
static override friendlyName = '목록에 값 넣기'
constructor(
- private target: IndexFetch,
- private value: Evaluable,
+ public target: IndexFetch,
+ public value: Evaluable,
public override tokens: Token[],
) {
super()
diff --git a/docs/index.md b/docs/index.md
index 2122e9f..10fdba4 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -30,17 +30,8 @@ features: