UNPKG

nadesiko3

Version:
295 lines (292 loc) 10.3 kB
/* eslint-disable no-undef */ import assert from 'assert' import { NakoCompiler } from '../src/nako3.mjs' import NakoIndent from '../src/nako_indent.mjs' describe('indent', async () => { const cmp = async (/** @type {string} */ code, /** @type {string} */ res) => { const nako = new NakoCompiler() const g = await nako.runAsync(code) assert.strictEqual(g.log, res) } it('もし', async () => { await cmp('!インデント構文\n' + 'もし1=1ならば\n' + '  1を表示\n', '1') await cmp('!インデント構文\n' + 'もし1=1ならば\n' + '  「わん」と表示。\n', 'わん') }) it('もし 違えば', async () => { await cmp('!インデント構文\n' + 'A=1\nもしA=1ならば\n' + '  1を表示\n' + '違えば\n' + '  2を表示\n', '1') await cmp('!インデント構文\n' + 'A=2\nもしA=1ならば\n' + '  1を表示\n' + '違えば\n' + '  2を表示\n', '2') }) it('5回', async () => { await cmp('!インデント構文\n' + 'N=0;5回\n' + '    N=N+1\n' + 'Nを表示;', '5') }) it('3回と5回', async () => { await cmp('!インデント構文\n' + 'N=0;5回\n' + '  3回\n' + '    N=N+1\n' + 'Nを表示;', '15') }) it('もし 違えば 入れ子', async () => { await cmp('!インデント構文\n' + 'A=1;B=1;もしA=1ならば\n' + '  もしB=1ならば\n' + '    1を表示\n' + '  違えば\n' + '    2を表示\n' + '違えば\n' + '  3を表示\n', '1') await cmp('!インデント構文\n' + 'A=2;B=1;もしA=1ならば\n' + '  もしB=1ならば\n' + '    1を表示\n' + '  違えば\n' + '    2を表示\n' + '違えば\n' + '  3を表示\n', '3') }) it('JSONで改行がある場合(#699)(core #46)', async () => { await cmp( '!インデント構文\n' + 'J={"taro":30,\n' + '  "jiro":50}\n' + 'J@"jiro"を表示\n' + '', '50') await cmp('' + '!インデント構文\n' + 'A=[99]\nもしA[0]=99ならば\n' + '  A=[0,\n0]\n' + 'A[0]を表示\n', '0') await cmp('' + '!インデント構文\n' + 'A={"a":0,"b":0}\nもし1ならば\n' + '  A={"a":99,\n"b":99}\n' + 'A["b"]を表示\n', '99') }) it('文字列内に改行がある場合', async () => { await cmp('!インデント構文\n' + 'S=「aaa\n' + 'bbb」\n' + 'もしS=30ならば\n' + '  「あ」と表示\n' + '違えば\n' + '  「o」と表示', 'o') }) it('コメント内に文字列リテラルの開始記号がある場合', async () => { await cmp('!インデント構文\n' + 'A=9;もしA=1ならば\n' + '  1を表示 # 「\n' + '2を表示\n', '2') await cmp('!インデント構文\n' + 'A=1;もしA=1ならば\n' + '  1を表示 // 「\n' + '2を表示\n', '1\n2') }) it('複数行コメント内に文字列リテラルの開始記号がある場合', async () => { await cmp('!インデント構文\n' + 'A=9;もしA=1ならば\n' + '  1を表示 /* 「 */\n' + '2を表示\n', '2') await cmp('!インデント構文\n' + 'A=1;もしA=1ならば\n' + '  1を表示 /* 「 */\n' + '2を表示\n', '1\n2') }) it('改行を含む、絵文字による文字列がある場合', async () => { await cmp( '!インデント構文\n' + '2回\n' + ' 🌴1\n' + '🌴を表示\n' + '「2」を表示\n', '1\n\n1\n\n2') }) it('前後が一致しない括弧がある場合', async () => { await cmp('!インデント構文\n' + '2回\n' + ' A={\n' + '}\n' + '1を表示\n', '1') }) it('「違えば」に行コメントがある場合', async () => { await cmp('!インデント構文\n' + 'A=2;もしA=1ならば\n' + '  1を表示\n' + '違えば # コメント\n' + '  2を表示\n', '2') }) it('「違えば」に範囲コメントがある場合', async () => { await cmp('!インデント構文\n' + 'A=2;もしA=1ならば\n' + '  1を表示\n' + '/* foo \n' + '*/違えば /* bar */\n' + '  2を表示\n', '2') }) it('コメントのみの行がある場合', async () => { await cmp('!インデント構文\n' + 'A=2;もしA=1ならば\n' + '    # コメント\n' + '  1を表示\n' + '違えば\n' + '/* */\n' + '/* */ \n' + '  2を表示\n', '2') }) it('"・"がある場合', async () => { await cmp('!インデント構文\n' + '1回\n' + '・1回\n' + '・・1を表示\n' + '・\n' + '・・2を表示\n', '1\n2') }) it('「違えばもし」の場合(#940)', async () => { await cmp('!インデント構文\n' + 'A=2;もしA=1ならば\n' + '  1を表示\n' + '違えば、もしA=2ならば\n' + '  2を表示\n' + '違えば\n' + '  3を表示\n', '2') }) // #1269 によりソースマップの確認は不要になりつつある it('ソースマップ', async () => { const result = NakoIndent.convert( '!インデント構文\n' + '\n' + '●(nを)階乗とは\n' + ' もしnが1と等しいならば\n' + ' それは1\n' + ' 違えば\n' + ' それは((n - 1)を階乗) * n\n' + '\n' + 'もし1=1なら\n' + ' 「こんに\n' + 'ちは」と表示\n' + '\n' + '「こんにちは」と表示\n' + '\n' + '' ) /** * 出力されるべきコード: * ``` * 0!インデント構文 * 1 ●(nを)階乗とは * 2 もしnが1と等しいならば * 3 それは1 * 4 違えば * 5 それは((n - 1)を階乗) * n * 6 ここまで‰ * 7 ここまで‰ * 8 もし1=1なら * 9 「こんに * 10 ちは」と表示 * 11 ここまで‰ * 12 「こんにちは」と表示 * ``` */ // 6, 7, 11 行目に「ここまで‰」が挿入された。 assert.deepStrictEqual(result.insertedLines, [6, 7, 11]) // 1, 6, 11, 13, 13行目の直前の空白行が消された。 // ※ 正確には、各空白行を消したときに、それまでに出力した行数(「ここまで‰」を含む)が 1, 6, 11, 13, 13 行。 assert.deepStrictEqual(result.deletedLines, [ { lineNumber: 1, len: 0 }, { lineNumber: 6, len: 0 }, { lineNumber: 11, len: 0 }, { lineNumber: 13, len: 0 }, { lineNumber: 13, len: 0 } ]) }) it('ブロック構造の取得', async () => { assert.deepStrictEqual( NakoIndent.getBlockStructure( 'もしはいならば\n' + ' 「こん\n' + 'にちは」を表示\n' + 'ここまで' ), { lines: [0, 4, 4, 0], // 各行の高さは 0, 4, 4, 0 pairs: [[0, 3]], // 0行目と3行目のペアがブロックを構成している。 parents: [null, 0, 0, null], spaces: ['', ' ', ' ', ''] } ) }) it('ブロック構造の取得 - 複数行にまたがる構文', async () => { // 複数行にまたがる文の2行目以降のインデントは、先頭行のインデントと等しいものとする。 // コメントのみの行のインデントは、直近の通常の行のインデントと等しいものとする。 assert.deepStrictEqual( NakoIndent.getBlockStructure( '!インデント構文\n' + 'Nを1から3まで繰り返す\n' + ' 「1行目\n' + '2行目」を表示\n' + '/*範囲コメント\n' + '*/' ), { lines: [0, 0, 4, 4, 4, 4], pairs: [[1, 6]], parents: [null, null, 1, 1, 1, 1], spaces: ['', '', ' ', ' ', '', ''] } ) }) it('ブロック構造の取得 - 違えば', async () => { assert.deepStrictEqual( NakoIndent.getBlockStructure( 'もしはいならば\n' + ' a\n' + '違えば\n' + ' b\n' + 'ここまで' ).pairs, [[0, 2], [2, 4]] ) }) it('2つ目の関数の定義が失敗する(#40)', async () => { await cmp('!インデント構文\n' + '●AAAとは\n' + '  それは30\n' + '●BBBとは\n' + '  それは50\n' + 'BBBを表示。', '50') }) it('インデント量: 半角スペース=1, 全角スペース=2, タブ=4', async () => { // 全角スペース1個はインデント量2 (半角スペース2個分) // eslint-disable-next-line no-irregular-whitespace await cmp('!インデント構文\n' + 'cを3から0まで繰り返す\n' + ' もしcが2以上ならば\n' + '  続ける\n' + ' cを表示\n', '1\n0') // 半角スペース2個はインデント量2 (全角スペース1個分) await cmp('!インデント構文\n' + 'cを3から0まで繰り返す\n' + ' もしcが2以上ならば\n' + '  続ける\n' + ' cを表示\n', '1\n0') // タブ1個はインデント量4 await cmp('!インデント構文\n' + 'cを3から0まで繰り返す\n' + '\tもしcが2以上ならば\n' + '\t\t続ける\n' + '\tcを表示\n', '1\n0') }) })