From cab1bf6ecb396279b7c0197bdc647d3e573b5850 Mon Sep 17 00:00:00 2001 From: Fine Archs Date: Fri, 17 May 2024 12:24:10 +0900 Subject: [PATCH 1/8] add while --- src/parser/plugins/validate-keyword.ts | 1 - src/parser/scanner.ts | 6 +++ src/parser/syntaxes/statements.ts | 54 ++++++++++++++++++++++++++ src/parser/token.ts | 2 + 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/parser/plugins/validate-keyword.ts b/src/parser/plugins/validate-keyword.ts index a179aba7..7a16aaac 100644 --- a/src/parser/plugins/validate-keyword.ts +++ b/src/parser/plugins/validate-keyword.ts @@ -44,7 +44,6 @@ const reservedWord = [ 'use', 'using', 'when', - 'while', 'yield', 'import', 'is', diff --git a/src/parser/scanner.ts b/src/parser/scanner.ts index 3b3aa6cd..1bba9fa7 100644 --- a/src/parser/scanner.ts +++ b/src/parser/scanner.ts @@ -367,6 +367,12 @@ export class Scanner implements ITokenStream { case 'loop': { return TOKEN(TokenKind.LoopKeyword, loc, { hasLeftSpacing }); } + case 'do': { + return TOKEN(TokenKind.DoKeyword, loc, { hasLeftSpacing }); + } + case 'while': { + return TOKEN(TokenKind.WhileKeyword, loc, { hasLeftSpacing }); + } case 'break': { return TOKEN(TokenKind.BreakKeyword, loc, { hasLeftSpacing }); } diff --git a/src/parser/syntaxes/statements.ts b/src/parser/syntaxes/statements.ts index 717ad579..d60b8d5b 100644 --- a/src/parser/syntaxes/statements.ts +++ b/src/parser/syntaxes/statements.ts @@ -45,6 +45,12 @@ export function parseStatement(s: ITokenStream): Ast.Node { case TokenKind.LoopKeyword: { return parseLoop(s); } + case TokenKind.DoKeyword: { + return parseDoWhile(s); + } + case TokenKind.WhileKeyword: { + return parseWhile(s); + } case TokenKind.BreakKeyword: { s.next(); return NODE('break', {}, loc); @@ -376,6 +382,54 @@ function parseLoop(s: ITokenStream): Ast.Node { return NODE('loop', { statements }, loc); } +/** + * ```abnf + * Loop = "do" BlockOrStatement "while" Expr + * ``` +*/ +function parseDoWhile(s: ITokenStream): Ast.Node { + const doLoc = s.token.loc; + s.nextWith(TokenKind.DoKeyword); + const body = parseBlockOrStatement(s); + const whileLoc = s.token.loc; + s.nextWith(TokenKind.WhileKeyword); + const cond = parseExpr(s, false); + + return NODE('loop', { + statements: [ + body, + NODE('if', { + cond: NODE('not', { expr: cond }, whileLoc), + then: NODE('break', {}, whileLoc), + elseif: [], + }, whileLoc), + ], + }, doLoc); +} + +/** + * ```abnf + * Loop = "while" Expr BlockOrStatement + * ``` +*/ +function parseWhile(s: ITokenStream): Ast.Node { + const loc = s.token.loc; + s.nextWith(TokenKind.WhileKeyword); + const cond = parseExpr(s, false); + const body = parseBlockOrStatement(s); + + return NODE('loop', { + statements: [ + NODE('if', { + cond: NODE('not', { expr: cond }, loc), + then: NODE('break', {}, loc), + elseif: [], + }, loc), + body, + ], + }, loc); +} + /** * ```abnf * Assign = Expr ("=" / "+=" / "-=") Expr diff --git a/src/parser/token.ts b/src/parser/token.ts index 67aca6b6..c07030c7 100644 --- a/src/parser/token.ts +++ b/src/parser/token.ts @@ -19,6 +19,8 @@ export enum TokenKind { EachKeyword, ForKeyword, LoopKeyword, + DoKeyword, + WhileKeyword, BreakKeyword, ContinueKeyword, MatchKeyword, From 8f38f9bfae1f02fff3a17b5a2f116a54fe716619 Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Fri, 17 May 2024 12:29:29 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=E6=B6=88=E3=81=97=E5=BF=98=E3=82=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/plugins/validate-keyword.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/parser/plugins/validate-keyword.ts b/src/parser/plugins/validate-keyword.ts index 7a16aaac..97b1a3cf 100644 --- a/src/parser/plugins/validate-keyword.ts +++ b/src/parser/plugins/validate-keyword.ts @@ -19,7 +19,6 @@ const reservedWord = [ 'constructor', // 'def', 'dictionary', - 'do', 'enum', 'export', 'finally', From 8fe342e3e8050777a36f983855e756a7eb299ec6 Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Sat, 18 May 2024 15:57:41 +0900 Subject: [PATCH 3/8] Create while.md --- unreleased/while.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased/while.md diff --git a/unreleased/while.md b/unreleased/while.md new file mode 100644 index 00000000..c49dc5c1 --- /dev/null +++ b/unreleased/while.md @@ -0,0 +1 @@ +- while文とdo-while文を追加 From bff6cc7da00595dc5186af4bbc1021c09f90ab8b Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Mon, 20 May 2024 08:05:29 +0900 Subject: [PATCH 4/8] Update doc --- docs/syntax.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/syntax.md b/docs/syntax.md index 15b7a419..f15479ab 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -182,6 +182,35 @@ each let v, arr{ // Syntax Error } ``` +### while + +```js +var count = 0 +while count < 42 { + count += 1 +} +<: count // 42 +// 条件が最初からfalseの場合 +while false { + <: 'hoge' +} // no output +``` + +### do-while +条件がtrueの間ループを続けます。 +条件が最初からfalseであってもループは一度実行されます。 +```js +var count = 0 +do { + count += 1 +} while count < 42 +<: count // 42 +// 条件が最初からfalseの場合 +while false { + <: 'hoge' +} // hoge +``` + ### loop `break`されるまで無制限にループを行います。 ```js From aa250a9b455bb69c8be73dfc117a343907fa464f Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Mon, 20 May 2024 17:50:25 +0900 Subject: [PATCH 5/8] fix doc --- docs/syntax.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/syntax.md b/docs/syntax.md index f15479ab..e0b0ac7d 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -183,7 +183,8 @@ each let v, arr{ // Syntax Error ``` ### while - +条件がtrueの間ループを続けます。 +条件が最初からfalseの場合はループは実行されません。 ```js var count = 0 while count < 42 { From 5160d45614f9838fef505aaa3e340cf6bc09025d Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Mon, 27 May 2024 20:36:49 +0900 Subject: [PATCH 6/8] add test --- test/syntax.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/syntax.ts b/test/syntax.ts index eefb8b15..d092591c 100644 --- a/test/syntax.ts +++ b/test/syntax.ts @@ -758,6 +758,50 @@ describe('each', () => { }); }); +describe('while', () => { + test.concurrent('Basic', async () => { + const res = await exe(` + var count = 0 + while count < 42 { + count += 1 + } + <: count + `); + eq(res, NUM(42)); + }); + + test.concurrent('start false', async () => { + const res = await exe(` + while false { + <: 'hoge' + } + `); + eq(res, NULL); + }); +}); + +describe('do-while', () => { + test.concurrent('Basic', async () => { + const res = await exe(` + var count = 0 + do { + count += 1 + } while count < 42 + <: count + `); + eq(res, NUM(42)); + }); + + test.concurrent('start false', async () => { + const res = await exe(` + do { + <: 'hoge' + } while false + `); + eq(res, STR('hoge')); + }); +}); + describe('loop', () => { test.concurrent('Basic', async () => { const res = await exe(` From de55125bf5766069fd82e440c1192f9c82883d0a Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Mon, 27 May 2024 20:38:28 +0900 Subject: [PATCH 7/8] Update keywords.ts --- test/keywords.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/keywords.ts b/test/keywords.ts index 79848c5f..88f183a1 100644 --- a/test/keywords.ts +++ b/test/keywords.ts @@ -9,6 +9,8 @@ const reservedWords = [ 'false', 'each', 'for', + 'do', + 'while', 'loop', 'break', 'continue', From 6e6f22bcc8aa81f5c34113d14775961da6c65d57 Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Tue, 28 May 2024 20:40:06 +0900 Subject: [PATCH 8/8] test review Co-authored-by: uzmoi --- docs/syntax.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/syntax.md b/docs/syntax.md index e0b0ac7d..9962bb74 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -207,9 +207,9 @@ do { } while count < 42 <: count // 42 // 条件が最初からfalseの場合 -while false { +do { <: 'hoge' -} // hoge +} while false // hoge ``` ### loop