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: