nadesiko3 3.2.45 → 3.2.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cnako3.bat +5 -1
- package/package.json +1 -2
- package/release/_hash.txt +24 -24
- package/release/_script-tags.txt +13 -13
- package/release/command.json +1 -1
- package/release/command.json.js +1 -1
- package/release/command_cnako3.json +1 -1
- package/release/command_list.json +1 -1
- package/release/editor.js +1 -1
- package/release/nako_gen_async.js +1 -1
- package/release/stats.json +1 -1
- package/release/version.js +1 -1
- package/release/wnako3.js +1 -1
- package/release/wnako3webworker.js +1 -1
- package/src/nako_gen.js +17 -5
- package/src/nako_global.js +2 -1
- package/src/nako_lex_rules.js +4 -4
- package/src/nako_parser3.js +26 -10
- package/src/nako_prepare.js +5 -1
- package/src/nako_version.js +2 -2
- package/src/plugin_browser_ajax.js +2 -2
- package/src/plugin_browser_dom_parts.js +0 -1
- package/src/plugin_node.js +29 -0
- package/src/plugin_system.js +20 -2
- package/test/common/calc_test.js +5 -0
- package/test/common/lex_test.js +6 -0
- package/test/node/plugin_test.js +4 -2
package/src/nako_gen.js
CHANGED
|
@@ -40,14 +40,23 @@ class NakoGen {
|
|
|
40
40
|
// async method
|
|
41
41
|
if (gen.numAsyncFn > 0) {
|
|
42
42
|
let canAsync = true
|
|
43
|
-
if (window && window.navigator && window.navigator.userAgent) {
|
|
43
|
+
if (typeof(window) == 'object' && window.navigator && window.navigator.userAgent) {
|
|
44
44
|
const ua = window.navigator.userAgent
|
|
45
45
|
canAsync = (ua.indexOf('MSIE') === -1)
|
|
46
46
|
}
|
|
47
47
|
if (canAsync) {
|
|
48
|
-
js =
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
js = `
|
|
49
|
+
// <nadesiko3::gen::async>
|
|
50
|
+
(async () => { // async::main
|
|
51
|
+
${js}
|
|
52
|
+
}).call(this).catch(err => {
|
|
53
|
+
if (!(err instanceof this.NakoRuntimeError)) {
|
|
54
|
+
err = new this.NakoRuntimeError(err, this.__varslist[0].line);
|
|
55
|
+
}
|
|
56
|
+
this.logger.error(err);
|
|
57
|
+
throw err;
|
|
58
|
+
}); // async::main
|
|
59
|
+
// <nadesiko3::gen::async>\n`
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
|
|
@@ -1218,7 +1227,7 @@ try {
|
|
|
1218
1227
|
|
|
1219
1228
|
// 関数呼び出しで、引数の末尾にthisを追加する-システム情報を参照するため
|
|
1220
1229
|
args.push('__self')
|
|
1221
|
-
|
|
1230
|
+
let funcDef = 'function'
|
|
1222
1231
|
let funcBegin = ''
|
|
1223
1232
|
let funcEnd = ''
|
|
1224
1233
|
// setter?
|
|
@@ -1292,6 +1301,7 @@ try {
|
|
|
1292
1301
|
|
|
1293
1302
|
let funcCall = `${res.js}(${argsCode})`
|
|
1294
1303
|
if (func.asyncFn) {
|
|
1304
|
+
funcDef = `async ${funcDef}`
|
|
1295
1305
|
funcCall = `await ${funcCall}`
|
|
1296
1306
|
this.numAsyncFn++
|
|
1297
1307
|
}
|
|
@@ -1325,6 +1335,7 @@ try {
|
|
|
1325
1335
|
|
|
1326
1336
|
let code = ''
|
|
1327
1337
|
if (func.return_none) {
|
|
1338
|
+
// 戻り値のない関数の場合
|
|
1328
1339
|
if (funcEnd === '') {
|
|
1329
1340
|
if (funcBegin === '') {
|
|
1330
1341
|
code = `${funcCall};\n`
|
|
@@ -1335,6 +1346,7 @@ try {
|
|
|
1335
1346
|
code = `${funcBegin}try {\n${indent(funcCall, 1)};\n} finally {\n${indent(funcEnd, 1)}}\n`
|
|
1336
1347
|
}
|
|
1337
1348
|
} else {
|
|
1349
|
+
// 戻り値のある関数の場合
|
|
1338
1350
|
let sorePrefex = ''
|
|
1339
1351
|
if (this.speedMode.invalidSore === 0) {
|
|
1340
1352
|
sorePrefex = `${this.varname('それ')} = `
|
package/src/nako_global.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const NakoColors = require('./nako_colors')
|
|
2
|
-
|
|
2
|
+
const {NakoRuntimeError} = require('./nako_errors')
|
|
3
3
|
/**
|
|
4
4
|
* コンパイルされたなでしこのプログラムで、グローバル空間のthisが指すオブジェクト
|
|
5
5
|
*/
|
|
@@ -23,6 +23,7 @@ class NakoGlobal {
|
|
|
23
23
|
this.__stack = []
|
|
24
24
|
this.__labels = []
|
|
25
25
|
this.__genMode = gen.genMode
|
|
26
|
+
this.NakoRuntimeError = NakoRuntimeError
|
|
26
27
|
|
|
27
28
|
// PluginSystemとdestroy()から参照するため
|
|
28
29
|
this.__module = { ...compiler.__module } // shallow copy
|
package/src/nako_lex_rules.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* なでしこ3字句解析のためのルール
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const kanakanji = /^[\u3005\u4E00-\u9FCF_a-zA-Z0-9
|
|
5
|
+
const kanakanji = /^[\u3005\u4E00-\u9FCF_a-zA-Z0-9ァ-ヶー\u2460-\u24FF\u2776-\u277F\u3251-\u32BF]+/
|
|
6
6
|
const nakoJosiList = require('./nako_josi_list')
|
|
7
7
|
const josiRE = nakoJosiList.josiRE
|
|
8
8
|
const removeJosiMap = nakoJosiList.removeJosiMap
|
|
@@ -53,9 +53,9 @@ module.exports = {
|
|
|
53
53
|
{ name: 'lteq', pattern: /^(≦|<=|=<)/ },
|
|
54
54
|
{ name: 'noteq', pattern: /^(≠|<>|!=)/ },
|
|
55
55
|
{ name: '←', pattern: /^(←|<--)/ }, // 関数呼び出し演算子 #891 #899
|
|
56
|
-
{ name: 'eq', pattern:
|
|
56
|
+
{ name: 'eq', pattern: /^(=|🟰)/ },
|
|
57
57
|
{ name: 'line_comment', pattern: /^!(インデント構文|ここまでだるい)[^\n]*/ },
|
|
58
|
-
{ name: 'not', pattern:
|
|
58
|
+
{ name: 'not', pattern: /^(!|💡)/ }, // #1184
|
|
59
59
|
{ name: 'gt', pattern: /^>/ },
|
|
60
60
|
{ name: 'lt', pattern: /^</ },
|
|
61
61
|
{ name: 'and', pattern: /^(かつ|&&)/ },
|
|
@@ -96,7 +96,7 @@ module.exports = {
|
|
|
96
96
|
// 単語句
|
|
97
97
|
{
|
|
98
98
|
name: 'word',
|
|
99
|
-
pattern: /^[_a-zA-Z\u3005\u4E00-\u9FCF
|
|
99
|
+
pattern: /^[_a-zA-Z\u3005\u4E00-\u9FCFぁ-んァ-ヶ\u2460-\u24FF\u2776-\u277F\u3251-\u32BF]/,
|
|
100
100
|
cbParser: cbWordParser
|
|
101
101
|
}
|
|
102
102
|
],
|
package/src/nako_parser3.js
CHANGED
|
@@ -551,13 +551,13 @@ class NakoParser extends NakoParserBase {
|
|
|
551
551
|
}
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
-
/**
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const args = [
|
|
554
|
+
/**
|
|
555
|
+
* 1つ目の値を与え、その後に続く計算式を取得し、優先規則に沿って並び替えして戻す
|
|
556
|
+
* @param {Ast | null} firstValue
|
|
557
|
+
* @returns {Ast | null}
|
|
558
|
+
*/
|
|
559
|
+
yGetArgOperator (firstValue) {
|
|
560
|
+
const args = [firstValue]
|
|
561
561
|
while (!this.isEOF()) {
|
|
562
562
|
// 演算子がある?
|
|
563
563
|
const op = this.peek()
|
|
@@ -568,7 +568,7 @@ class NakoParser extends NakoParserBase {
|
|
|
568
568
|
if (v === null) {
|
|
569
569
|
throw NakoSyntaxError.fromNode(
|
|
570
570
|
`計算式で演算子『${op.value}』後に値がありません`,
|
|
571
|
-
|
|
571
|
+
firstValue)
|
|
572
572
|
}
|
|
573
573
|
args.push(v)
|
|
574
574
|
continue
|
|
@@ -580,6 +580,15 @@ class NakoParser extends NakoParserBase {
|
|
|
580
580
|
return this.infixToAST(args)
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
+
/** @returns {Ast | null} */
|
|
584
|
+
yGetArg () {
|
|
585
|
+
// 値を一つ読む
|
|
586
|
+
const value1 = this.yValue()
|
|
587
|
+
if (value1 === null) { return null }
|
|
588
|
+
// 計算式がある場合を考慮
|
|
589
|
+
return this.yGetArgOperator(value1)
|
|
590
|
+
}
|
|
591
|
+
|
|
583
592
|
infixToPolish (list) {
|
|
584
593
|
// 中間記法から逆ポーランドに変換
|
|
585
594
|
const priority = (t) => {
|
|
@@ -832,8 +841,11 @@ class NakoParser extends NakoParserBase {
|
|
|
832
841
|
yReturn () {
|
|
833
842
|
const map = this.peekSourceMap()
|
|
834
843
|
if (!this.check('戻る')) { return null }
|
|
835
|
-
this.get() // skip '戻る'
|
|
844
|
+
const modoru = this.get() // skip '戻る'
|
|
836
845
|
const v = this.popStack(['で', 'を'])
|
|
846
|
+
if (this.stack.length > 0) {
|
|
847
|
+
throw NakoSyntaxError.fromNode('『戻』文の直前に未解決の引数があります。『(式)を戻す』のように式をカッコで括ってください。', modoru)
|
|
848
|
+
}
|
|
837
849
|
return {
|
|
838
850
|
type: 'return',
|
|
839
851
|
value: v,
|
|
@@ -1101,7 +1113,11 @@ class NakoParser extends NakoParserBase {
|
|
|
1101
1113
|
this.pushStack(r)
|
|
1102
1114
|
continue
|
|
1103
1115
|
}
|
|
1104
|
-
|
|
1116
|
+
// 関数呼び出しの直後に、四則演算があるか?
|
|
1117
|
+
if (!this.checkTypes(operatorList)) { return r } // なければ関数呼び出しを戻す
|
|
1118
|
+
// 四則演算があった場合、計算してスタックに載せる
|
|
1119
|
+
this.pushStack(this.yGetArgOperator(r))
|
|
1120
|
+
continue
|
|
1105
1121
|
}
|
|
1106
1122
|
// 値のとき → スタックに載せる
|
|
1107
1123
|
const t = this.yGetArg()
|
package/src/nako_prepare.js
CHANGED
|
@@ -122,7 +122,11 @@ class NakoPrepare {
|
|
|
122
122
|
0x3011: ']', // '】'
|
|
123
123
|
// 読点は「,」に変換する (#877)
|
|
124
124
|
0x3001: ',', // 読点 --- JSON記法で「,」と「、」を区別したいので読点は変換しないことに。(#276)
|
|
125
|
-
0xFF0C: ',' // 読点 ',' 論文などで利用、ただし句点はドットと被るので変換しない (#735)
|
|
125
|
+
0xFF0C: ',', // 読点 ',' 論文などで利用、ただし句点はドットと被るので変換しない (#735)
|
|
126
|
+
0x2716: '*', // ×の絵文字 (#1183)
|
|
127
|
+
0x2795: '+', // +の絵文字 (#1183)
|
|
128
|
+
0x2796: '-', // -の絵文字 (#1183)
|
|
129
|
+
0x2797: '÷' // ÷の絵文字 (#1183)
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
132
|
|
package/src/nako_version.js
CHANGED
|
@@ -380,7 +380,7 @@ module.exports = {
|
|
|
380
380
|
const txt = await res.text()
|
|
381
381
|
return txt
|
|
382
382
|
},
|
|
383
|
-
return_none:
|
|
383
|
+
return_none: false
|
|
384
384
|
},
|
|
385
385
|
'AJAX_JSON取得': { // @AJAXでURLにアクセスしJSONの結果を得て、送信時AJAXオプションの値を参照。 // @AJAX_JSONしゅとく
|
|
386
386
|
type: 'func',
|
|
@@ -394,6 +394,6 @@ module.exports = {
|
|
|
394
394
|
const txt = await res.json()
|
|
395
395
|
return txt
|
|
396
396
|
},
|
|
397
|
-
return_none:
|
|
397
|
+
return_none: false
|
|
398
398
|
},
|
|
399
399
|
}
|
package/src/plugin_node.js
CHANGED
|
@@ -902,6 +902,35 @@ const PluginNode = {
|
|
|
902
902
|
},
|
|
903
903
|
return_none: true
|
|
904
904
|
},
|
|
905
|
+
// @新AJAX
|
|
906
|
+
'AJAXテキスト取得': { // @AJAXでURLにアクセスしテキスト形式で結果を得る。送信時AJAXオプションの値を参照。 // @AJAXてきすとしゅとく
|
|
907
|
+
type: 'func',
|
|
908
|
+
josi: [['から']],
|
|
909
|
+
pure: true,
|
|
910
|
+
asyncFn: true,
|
|
911
|
+
fn: async function (url, sys) {
|
|
912
|
+
let options = sys.__v0['AJAXオプション']
|
|
913
|
+
if (options === '') { options = { method: 'GET' } }
|
|
914
|
+
const res = await fetch(url, options)
|
|
915
|
+
const txt = await res.text()
|
|
916
|
+
return txt
|
|
917
|
+
},
|
|
918
|
+
return_none: false
|
|
919
|
+
},
|
|
920
|
+
'AJAX_JSON取得': { // @AJAXでURLにアクセスしJSONの結果を得て、送信時AJAXオプションの値を参照。 // @AJAX_JSONしゅとく
|
|
921
|
+
type: 'func',
|
|
922
|
+
josi: [['から']],
|
|
923
|
+
pure: true,
|
|
924
|
+
asyncFn: true,
|
|
925
|
+
fn: async function (url, sys) {
|
|
926
|
+
let options = sys.__v0['AJAXオプション']
|
|
927
|
+
if (options === '') { options = { method: 'GET' } }
|
|
928
|
+
const res = await fetch(url, options)
|
|
929
|
+
const txt = await res.json()
|
|
930
|
+
return txt
|
|
931
|
+
},
|
|
932
|
+
return_none: false
|
|
933
|
+
},
|
|
905
934
|
// @文字コード
|
|
906
935
|
'文字コード変換サポート判定': { // @文字コードCODEをサポートしているか確認 // @もじこーどさぽーとはんてい
|
|
907
936
|
type: 'func',
|
package/src/plugin_system.js
CHANGED
|
@@ -194,7 +194,7 @@ const PluginSystem = {
|
|
|
194
194
|
},
|
|
195
195
|
return_none: true
|
|
196
196
|
},
|
|
197
|
-
'継続表示': { // @Sを改行なしで表示 // @けいぞくひょうじ
|
|
197
|
+
'継続表示': { // @Sを改行なしで表示(ただし「表示」命令を使うことで画面出力される) // @けいぞくひょうじ
|
|
198
198
|
type: 'func',
|
|
199
199
|
josi: [['を', 'と']],
|
|
200
200
|
pure: true,
|
|
@@ -475,6 +475,15 @@ const PluginSystem = {
|
|
|
475
475
|
},
|
|
476
476
|
return_none: true
|
|
477
477
|
},
|
|
478
|
+
'敬具': { // @ソースコードを読む人を気持ちよくする // @けいぐ
|
|
479
|
+
type: 'func',
|
|
480
|
+
josi: [],
|
|
481
|
+
pure: true,
|
|
482
|
+
fn: function (sys) {
|
|
483
|
+
sys.__reisetu += 100 // bonus point
|
|
484
|
+
},
|
|
485
|
+
return_none: true
|
|
486
|
+
},
|
|
478
487
|
'礼節レベル取得': { // @(お遊び)敬語を何度使ったか返す // @おねがいします
|
|
479
488
|
type: 'func',
|
|
480
489
|
josi: [],
|
|
@@ -693,7 +702,7 @@ const PluginSystem = {
|
|
|
693
702
|
return parseFloat(v)
|
|
694
703
|
}
|
|
695
704
|
},
|
|
696
|
-
'NAN判定': { // @値VがNaNかどうかを判定 // @NANはんてい
|
|
705
|
+
'NAN判定': { // @値VがNaNかどうかを判定(命令『非数判定』を使う事を推奨) // @NANはんてい
|
|
697
706
|
type: 'func',
|
|
698
707
|
josi: [['を']],
|
|
699
708
|
pure: true,
|
|
@@ -701,6 +710,15 @@ const PluginSystem = {
|
|
|
701
710
|
return isNaN(v)
|
|
702
711
|
}
|
|
703
712
|
},
|
|
713
|
+
'非数判定': { // @値Vが非数かどうかを判定(NAN判定より堅牢) // @ひすうはんてい
|
|
714
|
+
type: 'func',
|
|
715
|
+
josi: [['を']],
|
|
716
|
+
pure: true,
|
|
717
|
+
fn: function (v) {
|
|
718
|
+
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
|
|
719
|
+
return Number.isNaN(v)
|
|
720
|
+
}
|
|
721
|
+
},
|
|
704
722
|
'HEX': { // @値Vを16進数に変換 // @HEX
|
|
705
723
|
type: 'func',
|
|
706
724
|
josi: [['の']],
|
package/test/common/calc_test.js
CHANGED
|
@@ -136,4 +136,9 @@ describe('calc_test.js', () => {
|
|
|
136
136
|
cmp('N=「」;もし、N=0ならば「OK」と表示。', 'OK')
|
|
137
137
|
cmp('N=「」;もし、N===0ならば「NG」と表示。違えば「OK」と表示。', 'OK')
|
|
138
138
|
})
|
|
139
|
+
it('なでしこ式関数呼び出しで、途中に四則演算がある場合の処理 (#1188)', () => {
|
|
140
|
+
cmp('3.14のINT+2を表示。', '5')
|
|
141
|
+
cmp('3の5倍×2を表示', '30')
|
|
142
|
+
cmp('1+3の2倍×2を表示', '16')
|
|
143
|
+
})
|
|
139
144
|
})
|
package/test/common/lex_test.js
CHANGED
|
@@ -146,4 +146,10 @@ describe('lex_test', () => {
|
|
|
146
146
|
it('助詞の前後に空白があるとエラーになる問題 #1079', () => {
|
|
147
147
|
cmp('x=1;x と 2 と "3" を連続表示', '123')
|
|
148
148
|
})
|
|
149
|
+
it('丸付き数字が変数名として使えない #1185', () => {
|
|
150
|
+
cmp('⓪=0;①=1;㊿=50;❿=10;⓪+①+㊿+❿を表示', '61')
|
|
151
|
+
})
|
|
152
|
+
it('絵文字の四則演算を認識する #1183', () => {
|
|
153
|
+
cmp('リンゴ🟰3✖5;ミカン🟰9➗3;リンゴ+ミカンを表示', '18')
|
|
154
|
+
})
|
|
149
155
|
})
|
package/test/node/plugin_test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const assert = require('assert')
|
|
2
2
|
const CNako3 = require('../../src/cnako3')
|
|
3
|
-
|
|
3
|
+
const path = require('path')
|
|
4
4
|
describe('plugin_test', () => {
|
|
5
5
|
const nako = new CNako3()
|
|
6
6
|
// nako.logger.addListener('trace', ({ browserConsole }) => { console.log(...browserConsole) })
|
|
@@ -11,6 +11,8 @@ describe('plugin_test', () => {
|
|
|
11
11
|
assert.strictEqual(ret.log, res)
|
|
12
12
|
}
|
|
13
13
|
it('「取り込む」', () => {
|
|
14
|
-
|
|
14
|
+
const plug = path.join(__dirname, '..', '..', 'src', 'plugin_keigo.js')
|
|
15
|
+
cmp(`!「${plug}」を取り込む。\n拝啓。お世話になっております。礼節レベル取得して表示。`, '1')
|
|
15
16
|
})
|
|
16
17
|
})
|
|
18
|
+
|