diff --git a/core/src/nako_lex_rules.mts b/core/src/nako_lex_rules.mts index 30605885..d36bc5aa 100644 --- a/core/src/nako_lex_rules.mts +++ b/core/src/nako_lex_rules.mts @@ -44,16 +44,18 @@ export const rules: NakoLexRule[] = [ { name: 'range_comment', pattern: /^\/\*/, cbParser: cbRangeComment }, { name: 'def_test', pattern: /^●テスト:/ }, { name: 'def_func', pattern: /^●/ }, + { name: '…', pattern: /^…/ }, // 範囲オブジェクト(#1704) + { name: '…', pattern: /^\.{2,3}/ }, // 範囲オブジェクト(#1704) // 多倍長整数リテラルの判定。整数の末尾に「n」がついているだけな為、数値判定より上に書かないとただの整数にされる { name: 'bigint', pattern: /^0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*n/, readJosi: true }, { name: 'bigint', pattern: /^0[oO][0-7]+(_[0-7]+)*n/, readJosi: true }, { name: 'bigint', pattern: /^0[bB][0-1]+(_[0-1]+)*n/, readJosi: true }, { name: 'bigint', pattern: /^\d+(_\d+)*?n/, readJosi: true }, - // 数値の判定 --- この後nako_lexerにて単位を読む処理が入る(#994) + // 16進/8進/2進法の数値判定 --- この後nako_lexerにて単位を読む処理が入る(#994) { name: 'number', pattern: /^0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*/, readJosi: true, cb: parseNumber }, { name: 'number', pattern: /^0[oO][0-7]+(_[0-7]+)*/, readJosi: true, cb: parseNumber }, { name: 'number', pattern: /^0[bB][0-1]+(_[0-1]+)*/, readJosi: true, cb: parseNumber }, - // 下の三つは小数点が挟まっている場合、小数点から始まっている場合、小数点がない場合の十進法の数値にマッチします + // 下の三つは小数点が挟まっている場合、小数点から始まっている場合、小数点がない場合の十進法の数値にマッチする { name: 'number', pattern: /^\d+(_\d+)*\.(\d+(_\d+)*)?([eE][+|-]?\d+(_\d+)*)?/, readJosi: true, cb: parseNumber }, { name: 'number', pattern: /^\.\d+(_\d+)*([eE][+|-]?\d+(_\d+)*)?/, readJosi: true, cb: parseNumber }, { name: 'number', pattern: /^\d+(_\d+)*([eE][+|-]?\d+(_\d+)*)?/, readJosi: true, cb: parseNumber }, diff --git a/core/src/nako_parser3.mts b/core/src/nako_parser3.mts index 75e75a84..ed25e36d 100644 --- a/core/src/nako_parser3.mts +++ b/core/src/nako_parser3.mts @@ -617,10 +617,31 @@ export class NakoParser extends NakoParserBase { return this.infixToAST(args) } + yRange (kara: Ast): Ast|null { + // 範囲オブジェクト? + if (!this.check('…')) { return null } + const map = this.peekSourceMap() + this.get() // skip '…' + const made = this.yValue() + if (!kara || !made) { + throw NakoSyntaxError.fromNode('範囲オブジェクトの指定エラー。『A…B』の書式で指定してください。', map) + } + return { + type: 'func', + name: '範囲', + args: [kara, made], + josi: made.josi, + ...map, + end: this.peekSourceMap() + } + } + yGetArg (): Ast|null { // 値を一つ読む const value1 = this.yValue() if (value1 === null) { return null } + // 範囲オブジェクト? + if (this.check('…')) { return this.yRange(value1) } // 計算式がある場合を考慮 return this.yGetArgOperator(value1) } diff --git a/core/src/nako_types.mts b/core/src/nako_types.mts index 00462c3c..3119c3d0 100644 --- a/core/src/nako_types.mts +++ b/core/src/nako_types.mts @@ -152,6 +152,7 @@ export interface NakoEvent { callback: (event: any) => void } +/// 範囲オブジェクト (#1704) export interface RangeObject { 先頭: number, 末尾: number, diff --git a/core/test/literal_test.mjs b/core/test/literal_test.mjs index 4abc6a98..619d5a27 100644 --- a/core/test/literal_test.mjs +++ b/core/test/literal_test.mjs @@ -84,4 +84,9 @@ describe('literal_test', async () => { await cmp('-0b10111010110nの変数型確認して表示', 'bigint') await cmp('123_456_789nの変数型確認して表示', 'bigint') }) + it('範囲オブジェクトのテスト #1704', async () => { + await cmp('A=1…5;「{A@"先頭"}:{A@"末尾"}」を表示', '1:5') + await cmp('A=1...5;「{A@"先頭"}:{A@"末尾"}」を表示', '1:5') + await cmp('A=1;B=5;C=A...B;「{C@"先頭"}:{C@"末尾"}」を表示', '1:5') + }) })