nadesiko3 3.7.21 → 3.7.22
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/batch/command.txt +370 -334
- package/batch/jsplugin2text.nako3 +1 -1
- package/batch/pickup_command.nako3 +12 -0
- package/core/command/snako.mts +5 -1
- package/core/deno/snako.ts +5 -1
- package/core/package-lock.json +382 -21
- package/core/package.json +4 -4
- package/core/src/nako3.mts +178 -614
- package/core/src/nako_basic_plugins.mts +39 -0
- package/core/src/nako_core_version.mts +2 -2
- package/core/src/nako_csv.mts +0 -1
- package/core/src/nako_event.mts +49 -0
- package/core/src/nako_gen.mts +291 -202
- package/core/src/nako_indent_inline.mts +2 -2
- package/core/src/nako_lex_rules.mts +1 -1
- package/core/src/nako_parser3.mts +106 -165
- package/core/src/nako_parser_async.mts +97 -0
- package/core/src/nako_parser_base.mts +4 -55
- package/core/src/nako_parser_message.mts +105 -0
- package/core/src/nako_parser_operator.mts +93 -0
- package/core/src/nako_plugin_manager.mts +260 -0
- package/core/src/nako_require.mts +292 -0
- package/core/src/nako_runner.mts +191 -0
- package/core/src/nako_tokenizer.mts +221 -0
- package/core/src/plugin_csv.mts +1 -1
- package/core/src/plugin_system.mts +34 -3259
- package/core/src/plugin_system_array.mts +699 -0
- package/core/src/plugin_system_datetime.mts +368 -0
- package/core/src/plugin_system_debug.mts +403 -0
- package/core/src/plugin_system_dict.mts +85 -0
- package/core/src/plugin_system_json.mts +73 -0
- package/core/src/plugin_system_math.mts +383 -0
- package/core/src/plugin_system_regexp.mts +120 -0
- package/core/src/plugin_system_stdio.mts +86 -0
- package/core/src/plugin_system_string.mts +666 -0
- package/core/src/plugin_system_timer.mts +152 -0
- package/core/src/plugin_system_types.mts +151 -0
- package/core/src/plugin_system_url.mts +193 -0
- package/core/src/plugin_toml.mts +3 -3
- package/core/test/fixtures/README.md +39 -0
- package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
- package/core/test/fixtures/parser_ast_golden.json +8027 -0
- package/core/test/fixtures/parser_corpus.mjs +120 -0
- package/core/test/indent_test.mjs +6 -0
- package/core/test/nako_basic_plugins_test.mjs +44 -0
- package/core/test/nako_event_test.mjs +85 -0
- package/core/test/nako_gen_perf_test.mjs +178 -0
- package/core/test/nako_parser_async_test.mjs +112 -0
- package/core/test/nako_parser_test.mjs +160 -0
- package/core/test/nako_plugin_manager_test.mjs +185 -0
- package/core/test/nako_require_test.mjs +153 -0
- package/core/test/nako_runner_test.mjs +114 -0
- package/core/test/nako_tokenizer_test.mjs +115 -0
- package/core/test/plugin_system_debug_test.mjs +141 -0
- package/core/test/plugin_system_split_test.mjs +179 -0
- package/core/test/plugin_system_test.mjs +6 -0
- package/core/tsconfig.json +0 -1
- package/package.json +17 -21
- package/release/_hash.txt +36 -36
- package/release/_script-tags.txt +16 -16
- 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/edit_main.js +6 -6
- package/release/edit_main.js.map +3 -3
- package/release/editor.js +6 -6
- package/release/plugin_keigo.js.map +3 -3
- package/release/plugin_markup.js +46 -46
- package/release/plugin_markup.js.map +3 -3
- package/release/plugin_weykturtle3d.js +1 -1
- package/release/plugin_weykturtle3d.js.map +3 -3
- package/release/version.js +2 -2
- package/release/version_main.js +2 -2
- package/release/version_main.js.map +1 -1
- package/release/wnako3.js +186 -213
- package/release/wnako3.js.map +4 -4
- package/release/wnako3webworker.js +172 -199
- package/release/wnako3webworker.js.map +4 -4
- package/src/cnako3mod.mjs +7 -2
- package/src/cnako3mod.mts +7 -2
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser_ajax.mjs +4 -4
- package/src/plugin_browser_ajax.mts +4 -4
- package/src/plugin_browser_audio.mjs +10 -10
- package/src/plugin_browser_audio.mts +10 -10
- package/src/plugin_browser_camera.mjs +4 -4
- package/src/plugin_browser_camera.mts +4 -4
- package/src/plugin_browser_canvas.mjs +2 -2
- package/src/plugin_browser_canvas.mts +2 -2
- package/src/plugin_browser_crypto.mjs +3 -3
- package/src/plugin_browser_crypto.mts +3 -3
- package/src/plugin_browser_dom_event.mjs +1 -1
- package/src/plugin_browser_dom_event.mts +1 -1
- package/src/plugin_browser_geolocation.mjs +1 -1
- package/src/plugin_browser_geolocation.mts +1 -1
- package/src/plugin_browser_hotkey.mjs +1 -1
- package/src/plugin_browser_hotkey.mts +1 -1
- package/src/plugin_browser_html.mjs +1 -1
- package/src/plugin_browser_html.mts +1 -1
- package/src/plugin_browser_location.mjs +1 -1
- package/src/plugin_browser_location.mts +1 -1
- package/src/plugin_browser_speech.mjs +1 -1
- package/src/plugin_browser_speech.mts +1 -1
- package/src/plugin_browser_storage.mjs +2 -2
- package/src/plugin_browser_storage.mts +2 -2
- package/src/plugin_httpserver.mjs +3 -3
- package/src/plugin_httpserver.mts +3 -3
- package/src/plugin_keigo.mjs +2 -2
- package/src/plugin_keigo.mts +2 -2
- package/src/plugin_node.mjs +48 -48
- package/src/plugin_node.mts +53 -53
- package/src/plugin_weykturtle3d.mjs +56 -56
- package/src/plugin_weykturtle3d.mts +56 -56
- package/src/wnako3.mjs +1 -1
- package/src/wnako3.mts +1 -1
- package/src/wnako3_editor.mjs +5 -5
- package/src/wnako3_editor.mts +5 -5
- package/src/wnako3mod.mjs +2 -2
- package/src/wnako3mod.mts +2 -2
- package/core/src/nako3.mjs +0 -1021
- package/core/src/nako_ast.mjs +0 -4
- package/core/src/nako_colors.mjs +0 -77
- package/core/src/nako_core_version.mjs +0 -8
- package/core/src/nako_csv.mjs +0 -193
- package/core/src/nako_errors.mjs +0 -166
- package/core/src/nako_from_dncl.mjs +0 -285
- package/core/src/nako_from_dncl2.mjs +0 -347
- package/core/src/nako_gen.mjs +0 -2500
- package/core/src/nako_global.mjs +0 -138
- package/core/src/nako_indent.mjs +0 -442
- package/core/src/nako_indent_chars.mjs +0 -29
- package/core/src/nako_indent_inline.mjs +0 -361
- package/core/src/nako_josi_list.mjs +0 -47
- package/core/src/nako_lex_rules.mjs +0 -319
- package/core/src/nako_lexer.mjs +0 -794
- package/core/src/nako_logger.mjs +0 -221
- package/core/src/nako_parser3.mjs +0 -3250
- package/core/src/nako_parser_base.mjs +0 -403
- package/core/src/nako_parser_const.mjs +0 -37
- package/core/src/nako_prepare.mjs +0 -329
- package/core/src/nako_reserved_words.mjs +0 -42
- package/core/src/nako_source_mapping.mjs +0 -207
- package/core/src/nako_test.mjs +0 -37
- package/core/src/nako_token.mjs +0 -1
- package/core/src/nako_tools.mjs +0 -53
- package/core/src/nako_types.mjs +0 -14
- package/core/src/plugin_api.mjs +0 -4
- package/core/src/plugin_csv.mjs +0 -97
- package/core/src/plugin_math.mjs +0 -352
- package/core/src/plugin_promise.mjs +0 -102
- package/core/src/plugin_system.mjs +0 -3810
- package/core/src/plugin_test.mjs +0 -52
- package/core/src/plugin_toml.mjs +0 -39
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
* nadesiko v3 parser
|
|
4
|
+
*
|
|
5
|
+
* 再帰下降パーサ。トークン列を読み進めながら構文木(Ast)を組み立てる。
|
|
6
|
+
* 各構文規則は `yXxx` という名前のメソッドで、カーソル(this.index)と
|
|
7
|
+
* 計算用スタック(this.stack)を共有しながら相互に呼び合う。
|
|
8
|
+
* カーソル操作・スタック操作・変数検索は基底クラス NakoParserBase にある。
|
|
9
|
+
*
|
|
10
|
+
* ## 構文規則の呼び出し関係 (#2364)
|
|
11
|
+
*
|
|
12
|
+
* ```
|
|
13
|
+
* parse
|
|
14
|
+
* └ startParser → ySentenceList → ySentence ─┬ yIF / yAtohantei / yTryExcept / yDebugPrint
|
|
15
|
+
* ├ yDNCLMode / ySetGenMode / ySpeedMode ...
|
|
16
|
+
* ├ yLet ── yLetArrayAt / yLetArrayBracket
|
|
17
|
+
* ├ yDefFunc / yDefTest → yDefFuncCommon
|
|
18
|
+
* └ yCall ─┬ yDainyu / ySadameru / yIncDec
|
|
19
|
+
* ├ yRepeatTime / yWhile / yFor /
|
|
20
|
+
* │ yForEach / ySwitch / yReturn
|
|
21
|
+
* └ yCallFunc → yMumeiFunc
|
|
22
|
+
*
|
|
23
|
+
* yCalc → yGetArg ─┬ yRange
|
|
24
|
+
* ├ yGetArgOperator → infixToAST() … nako_parser_operator.mts
|
|
25
|
+
* └ yValue ─┬ yValueKakko / yValueWord / yMumeiFunc
|
|
26
|
+
* └ yJSONArray / yJSONObject → yJSONArrayValue /
|
|
27
|
+
* yJSONObjectValue → yCalc
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* 上の図は主要な流れだけを示したもので、実際には
|
|
31
|
+
* `ySentence ↔ yBlock ↔ yCall ↔ yCalc ↔ yValue ↔ yJSON*` が
|
|
32
|
+
* 大きな相互再帰を成している。この相互再帰があるため、構文規則そのものは
|
|
33
|
+
* ファイルを分けても結合が下がらない。分離してあるのは、
|
|
34
|
+
* 相互再帰の外側にあってカーソルにもスタックにも触れないものだけ。
|
|
35
|
+
*
|
|
36
|
+
* - `nako_parser_operator.mts` … 演算子の優先順位による構文木の組み立て
|
|
37
|
+
* - `nako_parser_async.mts` … 解析後に asyncFn を伝播させる後処理パス
|
|
38
|
+
* - `nako_parser_message.mts` … エラーメッセージの組み立て
|
|
4
39
|
*/
|
|
5
40
|
import { opPriority, RenbunJosi, operatorList } from './nako_parser_const.mjs'
|
|
6
41
|
import { NakoParserBase } from './nako_parser_base.mjs'
|
|
42
|
+
import { infixToAST } from './nako_parser_operator.mjs'
|
|
43
|
+
import { checkAsyncFn } from './nako_parser_async.mjs'
|
|
44
|
+
import { makeStackBalanceReport } from './nako_parser_message.mjs'
|
|
7
45
|
import { NakoSyntaxError } from './nako_errors.mjs'
|
|
8
46
|
import { NakoLexer } from './nako_lexer.mjs'
|
|
9
|
-
import { FuncListItemType,
|
|
47
|
+
import { FuncListItemType, NewEmptyToken, SourceMap } from './nako_types.mjs'
|
|
10
48
|
import { NodeType, Ast, AstEol, AstBlocks, AstOperator, AstConst, AstLet, AstLetArray, AstIf, AstWhile, AstAtohantei, AstFor, AstForeach, AstSwitch, AstRepeatTimes, AstDefFunc, AstCallFunc, AstStrValue, AstDefVar, AstDefVarList } from './nako_ast.mjs'
|
|
11
49
|
import { Token, TokenDefFunc, TokenCallFunc } from './nako_token.mjs'
|
|
12
50
|
|
|
@@ -27,12 +65,8 @@ export class NakoParser extends NakoParserBase {
|
|
|
27
65
|
const result = this.startParser()
|
|
28
66
|
|
|
29
67
|
// 関数毎に非同期処理が必要かどうかを判定する
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
while (this.isModifiedNodes) {
|
|
33
|
-
this.isModifiedNodes = false
|
|
34
|
-
this._checkAsyncFn(result)
|
|
35
|
-
}
|
|
68
|
+
// 「非同期関数を呼ぶ関数もまた非同期」と伝播していくので、変化が無くなるまで繰り返す
|
|
69
|
+
while (checkAsyncFn(result, this.funclist)) { /* 変化が無くなるまで繰り返す */ }
|
|
36
70
|
|
|
37
71
|
return result
|
|
38
72
|
}
|
|
@@ -79,34 +113,13 @@ export class NakoParser extends NakoParserBase {
|
|
|
79
113
|
return { type: 'block', blocks, josi: '', ...map, end: this.peekSourceMap() }
|
|
80
114
|
}
|
|
81
115
|
|
|
82
|
-
/** 余剰スタックのレポートを作る
|
|
116
|
+
/** 余剰スタックのレポートを作る
|
|
117
|
+
* (レポートの組み立ては nako_parser_message.mts の makeStackBalanceReport) #2364
|
|
118
|
+
*/
|
|
83
119
|
makeStackBalanceReport(): string {
|
|
84
|
-
const
|
|
85
|
-
this.stack.forEach((t) => {
|
|
86
|
-
let w = this.nodeToStr(t, { depth: 1 }, false)
|
|
87
|
-
if (t.josi) { w += t.josi }
|
|
88
|
-
words.push(w)
|
|
89
|
-
})
|
|
90
|
-
const desc = words.join(',')
|
|
91
|
-
// 最近使った関数の使い方レポートを作る #1093
|
|
92
|
-
let descFunc = ''
|
|
93
|
-
const chA = 'A'.charCodeAt(0)
|
|
94
|
-
for (const f of this.recentlyCalledFunc) {
|
|
95
|
-
descFunc += ' - '
|
|
96
|
-
let no = 0
|
|
97
|
-
const josiA: FuncArgs | undefined = (f).josi
|
|
98
|
-
if (josiA) {
|
|
99
|
-
for (const arg of josiA) {
|
|
100
|
-
const ch = String.fromCharCode(chA + no)
|
|
101
|
-
descFunc += ch
|
|
102
|
-
if (arg.length === 1) { descFunc += arg[0] } else { descFunc += `(${arg.join('|')})` }
|
|
103
|
-
no++
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
descFunc += String(f.name) + '\n'
|
|
107
|
-
}
|
|
120
|
+
const report = makeStackBalanceReport(this.stack, this.recentlyCalledFunc)
|
|
108
121
|
this.recentlyCalledFunc = []
|
|
109
|
-
return
|
|
122
|
+
return report
|
|
110
123
|
}
|
|
111
124
|
|
|
112
125
|
yEOL(): AstEol | null {
|
|
@@ -196,6 +209,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
196
209
|
return null
|
|
197
210
|
}
|
|
198
211
|
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
// 実行モードの指定と廃止された構文
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
|
|
199
216
|
/** [廃止] 非同期モード #11 @returns {Ast} */
|
|
200
217
|
yASyncMode(): Ast {
|
|
201
218
|
this.logger.error('『非同期モード』構文は廃止されました(https://nadesi.com/v3/doc/go.php?1028)。', this.peek())
|
|
@@ -240,6 +257,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
240
257
|
return { type: 'run_mode', value: mode, ...map, end: this.peekSourceMap() }
|
|
241
258
|
}
|
|
242
259
|
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
// ブロックと関数定義
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
|
|
243
264
|
/** @returns {AstBlocks} */
|
|
244
265
|
yBlock(): AstBlocks {
|
|
245
266
|
const map = this.peekSourceMap()
|
|
@@ -387,6 +408,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
387
408
|
}
|
|
388
409
|
}
|
|
389
410
|
|
|
411
|
+
// ---------------------------------------------------------------------------
|
|
412
|
+
// 条件分岐(もし文)
|
|
413
|
+
// ---------------------------------------------------------------------------
|
|
414
|
+
|
|
390
415
|
/** 「もし」文の条件を取得 */
|
|
391
416
|
yIFCond(): Ast {
|
|
392
417
|
const map = this.peekSourceMap()
|
|
@@ -534,6 +559,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
534
559
|
}
|
|
535
560
|
}
|
|
536
561
|
|
|
562
|
+
// ---------------------------------------------------------------------------
|
|
563
|
+
// 実行速度・パフォーマンスの指定
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
|
|
537
566
|
ySpeedMode(): AstBlocks | null {
|
|
538
567
|
const map: SourceMap = this.peekSourceMap()
|
|
539
568
|
if (!this.check2(['string', '実行速度優先'])) {
|
|
@@ -649,6 +678,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
649
678
|
return { type: 'eol', ...this.peekSourceMap(), end: this.peekSourceMap() }
|
|
650
679
|
}
|
|
651
680
|
|
|
681
|
+
// ---------------------------------------------------------------------------
|
|
682
|
+
// 引数の取得と演算子
|
|
683
|
+
// ---------------------------------------------------------------------------
|
|
684
|
+
|
|
652
685
|
/**
|
|
653
686
|
* 1つ目の値を与え、その後に続く計算式を取得し、優先規則に沿って並び替えして戻す
|
|
654
687
|
* @param {Ast} firstValue
|
|
@@ -675,7 +708,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
675
708
|
}
|
|
676
709
|
if (args.length === 0) { return null }
|
|
677
710
|
if (args.length === 1) { return args[0] }
|
|
678
|
-
return
|
|
711
|
+
return infixToAST(args, this.logger)
|
|
679
712
|
}
|
|
680
713
|
|
|
681
714
|
/**
|
|
@@ -743,76 +776,6 @@ export class NakoParser extends NakoParserBase {
|
|
|
743
776
|
return this.yGetArgOperator(value1)
|
|
744
777
|
}
|
|
745
778
|
|
|
746
|
-
infixToPolish(list: Ast[]): Ast[] {
|
|
747
|
-
// 中間記法から逆ポーランドに変換
|
|
748
|
-
const priority = (t: Ast) => {
|
|
749
|
-
if (opPriority[t.type]) { return opPriority[t.type] }
|
|
750
|
-
return 10
|
|
751
|
-
}
|
|
752
|
-
const stack: Ast[] = []
|
|
753
|
-
const polish: Ast[] = []
|
|
754
|
-
while (list.length > 0) {
|
|
755
|
-
const t = list.shift()
|
|
756
|
-
if (!t) { break }
|
|
757
|
-
while (stack.length > 0) { // 優先順位を見て移動する
|
|
758
|
-
const sTop = stack[stack.length - 1]
|
|
759
|
-
if (priority(t) > priority(sTop)) { break }
|
|
760
|
-
const tpop = stack.pop()
|
|
761
|
-
if (!tpop) {
|
|
762
|
-
this.logger.error('計算式に間違いがあります。', t)
|
|
763
|
-
break
|
|
764
|
-
}
|
|
765
|
-
polish.push(tpop)
|
|
766
|
-
}
|
|
767
|
-
stack.push(t)
|
|
768
|
-
}
|
|
769
|
-
// 残った要素を積み替える
|
|
770
|
-
while (stack.length > 0) {
|
|
771
|
-
const t = stack.pop()
|
|
772
|
-
if (t) { polish.push(t) }
|
|
773
|
-
}
|
|
774
|
-
return polish
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
/** @returns {Ast | null} */
|
|
778
|
-
infixToAST(list: Ast[]): Ast | null {
|
|
779
|
-
if (list.length === 0) { return null }
|
|
780
|
-
// 逆ポーランドを構文木に
|
|
781
|
-
const josi = list[list.length - 1].josi
|
|
782
|
-
const node = list[list.length - 1]
|
|
783
|
-
const polish = this.infixToPolish(list)
|
|
784
|
-
/** @type {Ast[]} */
|
|
785
|
-
const stack = []
|
|
786
|
-
for (const t of polish) {
|
|
787
|
-
if (!opPriority[t.type]) { // 演算子ではない
|
|
788
|
-
stack.push(t)
|
|
789
|
-
continue
|
|
790
|
-
}
|
|
791
|
-
const b:Ast|undefined = stack.pop()
|
|
792
|
-
const a:Ast|undefined = stack.pop()
|
|
793
|
-
if (a === undefined || b === undefined) {
|
|
794
|
-
this.logger.debug('--- 計算式(逆ポーランド) ---\n' + JSON.stringify(polish))
|
|
795
|
-
throw NakoSyntaxError.fromNode('計算式でエラー', node)
|
|
796
|
-
}
|
|
797
|
-
/** @type {AstOperator} */
|
|
798
|
-
const op: AstOperator = {
|
|
799
|
-
type: 'op',
|
|
800
|
-
operator: t.type,
|
|
801
|
-
blocks: [a, b],
|
|
802
|
-
josi,
|
|
803
|
-
startOffset: a.startOffset,
|
|
804
|
-
endOffset: a.endOffset,
|
|
805
|
-
line: a.line,
|
|
806
|
-
column: a.column,
|
|
807
|
-
file: a.file
|
|
808
|
-
}
|
|
809
|
-
stack.push(op)
|
|
810
|
-
}
|
|
811
|
-
const ans = stack.pop()
|
|
812
|
-
if (!ans) { return null }
|
|
813
|
-
return ans
|
|
814
|
-
}
|
|
815
|
-
|
|
816
779
|
yGetArgParen(y: Ast[], funcName?: string): Ast[] { // C言語風呼び出しでカッコの中を取得
|
|
817
780
|
let isClose = false
|
|
818
781
|
const si = this.stack.length
|
|
@@ -867,6 +830,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
867
830
|
return node
|
|
868
831
|
}
|
|
869
832
|
|
|
833
|
+
// ---------------------------------------------------------------------------
|
|
834
|
+
// 繰り返しと条件分岐の各構文
|
|
835
|
+
// ---------------------------------------------------------------------------
|
|
836
|
+
|
|
870
837
|
/** @returns {AstRepeatTimes | null} */
|
|
871
838
|
yRepeatTime(): AstRepeatTimes | null {
|
|
872
839
|
const map = this.peekSourceMap()
|
|
@@ -1202,6 +1169,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1202
1169
|
return ast
|
|
1203
1170
|
}
|
|
1204
1171
|
|
|
1172
|
+
// ---------------------------------------------------------------------------
|
|
1173
|
+
// 無名関数
|
|
1174
|
+
// ---------------------------------------------------------------------------
|
|
1175
|
+
|
|
1205
1176
|
/** 無名関数
|
|
1206
1177
|
* @returns {AstDefFunc|null}
|
|
1207
1178
|
*/
|
|
@@ -1263,6 +1234,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1263
1234
|
}
|
|
1264
1235
|
}
|
|
1265
1236
|
|
|
1237
|
+
// ---------------------------------------------------------------------------
|
|
1238
|
+
// 代入文と増減
|
|
1239
|
+
// ---------------------------------------------------------------------------
|
|
1240
|
+
|
|
1266
1241
|
/** 代入構文 */
|
|
1267
1242
|
yDainyu(): AstBlocks | null {
|
|
1268
1243
|
const map = this.peekSourceMap()
|
|
@@ -1380,6 +1355,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1380
1355
|
}
|
|
1381
1356
|
}
|
|
1382
1357
|
|
|
1358
|
+
// ---------------------------------------------------------------------------
|
|
1359
|
+
// 関数呼び出し
|
|
1360
|
+
// ---------------------------------------------------------------------------
|
|
1361
|
+
|
|
1383
1362
|
yCall(): Ast | null {
|
|
1384
1363
|
if (this.isEOF()) { return null }
|
|
1385
1364
|
|
|
@@ -1577,6 +1556,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1577
1556
|
return null
|
|
1578
1557
|
}
|
|
1579
1558
|
|
|
1559
|
+
// ---------------------------------------------------------------------------
|
|
1560
|
+
// 代入・変数定義と配列要素への代入
|
|
1561
|
+
// ---------------------------------------------------------------------------
|
|
1562
|
+
|
|
1580
1563
|
/** @returns {Ast | null} */
|
|
1581
1564
|
yLet(): AstBlocks | null {
|
|
1582
1565
|
const map = this.peekSourceMap()
|
|
@@ -2157,6 +2140,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2157
2140
|
return null
|
|
2158
2141
|
}
|
|
2159
2142
|
|
|
2143
|
+
// ---------------------------------------------------------------------------
|
|
2144
|
+
// 計算式と値
|
|
2145
|
+
// ---------------------------------------------------------------------------
|
|
2146
|
+
|
|
2160
2147
|
/** @returns {Ast | null} */
|
|
2161
2148
|
yCalc(): Ast|null {
|
|
2162
2149
|
const map = this.peekSourceMap()
|
|
@@ -2573,6 +2560,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2573
2560
|
return null
|
|
2574
2561
|
}
|
|
2575
2562
|
|
|
2563
|
+
// ---------------------------------------------------------------------------
|
|
2564
|
+
// 変数名の解決と登録
|
|
2565
|
+
// ---------------------------------------------------------------------------
|
|
2566
|
+
|
|
2576
2567
|
/** 変数を生成 */
|
|
2577
2568
|
createVar(word: Token|Ast, isConst: boolean, isExport: boolean): Token|Ast {
|
|
2578
2569
|
let gname: string = (word as AstStrValue).value
|
|
@@ -2630,6 +2621,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2630
2621
|
return words
|
|
2631
2622
|
}
|
|
2632
2623
|
|
|
2624
|
+
// ---------------------------------------------------------------------------
|
|
2625
|
+
// JSON/配列リテラル
|
|
2626
|
+
// ---------------------------------------------------------------------------
|
|
2627
|
+
|
|
2633
2628
|
yJSONObjectValue(): Ast[] {
|
|
2634
2629
|
// 戻り値の形式
|
|
2635
2630
|
// Astblocks.blocks = [key1, value1, key2, value2, key3, value3 ...]
|
|
@@ -2804,6 +2799,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2804
2799
|
return null
|
|
2805
2800
|
}
|
|
2806
2801
|
|
|
2802
|
+
// ---------------------------------------------------------------------------
|
|
2803
|
+
// エラー監視
|
|
2804
|
+
// ---------------------------------------------------------------------------
|
|
2805
|
+
|
|
2807
2806
|
/** エラー監視構文 */
|
|
2808
2807
|
yTryExcept(): AstBlocks | null {
|
|
2809
2808
|
const map = this.peekSourceMap()
|
|
@@ -2834,67 +2833,9 @@ export class NakoParser extends NakoParserBase {
|
|
|
2834
2833
|
}
|
|
2835
2834
|
}
|
|
2836
2835
|
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
// 関数定義があれば関数
|
|
2841
|
-
if (node.type === 'def_func' || node.type === 'def_test' || node.type === 'func_obj') {
|
|
2842
|
-
// 関数定義でasyncFnが指定されているならtrueを返す
|
|
2843
|
-
const def: AstDefFunc = node as AstDefFunc
|
|
2844
|
-
if (def.asyncFn) { return true } // 既にasyncFnが指定されている
|
|
2845
|
-
// 関数定義の中身を調べてasyncFnであるならtrueに変更する
|
|
2846
|
-
let isAsyncFn = false
|
|
2847
|
-
for (const n of def.blocks) {
|
|
2848
|
-
if (this._checkAsyncFn(n)) {
|
|
2849
|
-
isAsyncFn = true
|
|
2850
|
-
def.asyncFn = isAsyncFn
|
|
2851
|
-
def.meta.asyncFn = isAsyncFn
|
|
2852
|
-
this.isModifiedNodes = true
|
|
2853
|
-
return true
|
|
2854
|
-
}
|
|
2855
|
-
}
|
|
2856
|
-
}
|
|
2857
|
-
// 関数呼び出しを調べて非同期処理が必要ならtrueを返す
|
|
2858
|
-
if (node.type === 'func') {
|
|
2859
|
-
// 関数呼び出し自体が非同期処理ならtrueを返す
|
|
2860
|
-
const callNode: AstCallFunc = node as AstCallFunc
|
|
2861
|
-
if (callNode.asyncFn) {
|
|
2862
|
-
return true
|
|
2863
|
-
}
|
|
2864
|
-
// 続けて、以下の関数呼び出しの引数などに非同期処理があるかどうか調べる
|
|
2865
|
-
// 関数の引数は、node.blocksに格納されている
|
|
2866
|
-
if (callNode.blocks) {
|
|
2867
|
-
for (const n of callNode.blocks) {
|
|
2868
|
-
if (this._checkAsyncFn(n)) {
|
|
2869
|
-
callNode.asyncFn = true
|
|
2870
|
-
this.isModifiedNodes = true
|
|
2871
|
-
return true
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
// さらに、関数のリンクを調べる
|
|
2876
|
-
const func = this.funclist.get(callNode.name)
|
|
2877
|
-
if (func && func.asyncFn) {
|
|
2878
|
-
callNode.asyncFn = true
|
|
2879
|
-
this.isModifiedNodes = true
|
|
2880
|
-
return true
|
|
2881
|
-
}
|
|
2882
|
-
return false
|
|
2883
|
-
}
|
|
2884
|
-
// 連文 ... 現在、効率は悪いが非同期で実行することになっている
|
|
2885
|
-
if (node.type === 'renbun') {
|
|
2886
|
-
return true
|
|
2887
|
-
}
|
|
2888
|
-
// その他
|
|
2889
|
-
if ((node as AstBlocks).blocks) {
|
|
2890
|
-
for (const n of (node as AstBlocks).blocks) {
|
|
2891
|
-
if (this._checkAsyncFn(n)) {
|
|
2892
|
-
return true
|
|
2893
|
-
}
|
|
2894
|
-
}
|
|
2895
|
-
}
|
|
2896
|
-
return false
|
|
2897
|
-
}
|
|
2836
|
+
// ---------------------------------------------------------------------------
|
|
2837
|
+
// TokenからAstへの変換
|
|
2838
|
+
// ---------------------------------------------------------------------------
|
|
2898
2839
|
|
|
2899
2840
|
/** TokenをそのままNodeに変換するメソッド(ただし簡単なものだけ対応)
|
|
2900
2841
|
* @returns {Ast[]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 構文解析後の AST を走査して、非同期処理(asyncFn)の要否を判定するモジュール
|
|
3
|
+
*
|
|
4
|
+
* NakoParser から分離した (#2364)。
|
|
5
|
+
* 構文解析が完了した後に AST 全体を走査する後処理パスであり、
|
|
6
|
+
* トークンのカーソルにも計算用スタックにも一切触れない。
|
|
7
|
+
* (実体は nako_parser3.mts の NakoParser._checkAsyncFn だった)
|
|
8
|
+
*
|
|
9
|
+
* 非同期の情報は「非同期関数を呼ぶ関数もまた非同期」という形で伝播していくため、
|
|
10
|
+
* 1 回の走査では行き渡らないことがある。呼び出し側は変化が無くなるまで
|
|
11
|
+
* `checkAsyncFn()` を繰り返し呼ぶこと。
|
|
12
|
+
*/
|
|
13
|
+
import { Ast, AstBlocks, AstDefFunc, AstCallFunc } from './nako_ast.mjs'
|
|
14
|
+
import { FuncList } from './nako_types.mjs'
|
|
15
|
+
|
|
16
|
+
/** 走査中に AST を書き換えたかどうかを持ち回るための入れ物 */
|
|
17
|
+
interface CheckContext {
|
|
18
|
+
modified: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* AST を走査して関数ごとに asyncFn が必要かどうかを確認し、必要なら書き換える。
|
|
23
|
+
*
|
|
24
|
+
* @param node 走査対象の AST
|
|
25
|
+
* @param funclist 関数一覧(呼び出し先が非同期かどうかの判定に使う)
|
|
26
|
+
* @returns AST を書き換えたら true。呼び出し側は false になるまで繰り返すこと
|
|
27
|
+
*/
|
|
28
|
+
export function checkAsyncFn (node: Ast, funclist: FuncList): boolean {
|
|
29
|
+
const ctx: CheckContext = { modified: false }
|
|
30
|
+
checkNode(node, funclist, ctx)
|
|
31
|
+
return ctx.modified
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* ノードが非同期処理を含むかどうかを返す(必要に応じて AST を書き換える)
|
|
36
|
+
* @returns 非同期処理を含むなら true
|
|
37
|
+
*/
|
|
38
|
+
function checkNode (node: Ast, funclist: FuncList, ctx: CheckContext): boolean {
|
|
39
|
+
if (!node) { return false }
|
|
40
|
+
// 関数定義があれば関数
|
|
41
|
+
if (node.type === 'def_func' || node.type === 'def_test' || node.type === 'func_obj') {
|
|
42
|
+
// 関数定義でasyncFnが指定されているならtrueを返す
|
|
43
|
+
const def: AstDefFunc = node as AstDefFunc
|
|
44
|
+
if (def.asyncFn) { return true } // 既にasyncFnが指定されている
|
|
45
|
+
// 関数定義の中身を調べてasyncFnであるならtrueに変更する
|
|
46
|
+
let isAsyncFn = false
|
|
47
|
+
for (const n of def.blocks) {
|
|
48
|
+
if (checkNode(n, funclist, ctx)) {
|
|
49
|
+
isAsyncFn = true
|
|
50
|
+
def.asyncFn = isAsyncFn
|
|
51
|
+
def.meta.asyncFn = isAsyncFn
|
|
52
|
+
ctx.modified = true
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 関数呼び出しを調べて非同期処理が必要ならtrueを返す
|
|
58
|
+
if (node.type === 'func') {
|
|
59
|
+
// 関数呼び出し自体が非同期処理ならtrueを返す
|
|
60
|
+
const callNode: AstCallFunc = node as AstCallFunc
|
|
61
|
+
if (callNode.asyncFn) {
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
// 続けて、以下の関数呼び出しの引数などに非同期処理があるかどうか調べる
|
|
65
|
+
// 関数の引数は、node.blocksに格納されている
|
|
66
|
+
if (callNode.blocks) {
|
|
67
|
+
for (const n of callNode.blocks) {
|
|
68
|
+
if (checkNode(n, funclist, ctx)) {
|
|
69
|
+
callNode.asyncFn = true
|
|
70
|
+
ctx.modified = true
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// さらに、関数のリンクを調べる
|
|
76
|
+
const func = funclist.get(callNode.name)
|
|
77
|
+
if (func && func.asyncFn) {
|
|
78
|
+
callNode.asyncFn = true
|
|
79
|
+
ctx.modified = true
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
// 連文 ... 現在、効率は悪いが非同期で実行することになっている
|
|
85
|
+
if (node.type === 'renbun') {
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
// その他
|
|
89
|
+
if ((node as AstBlocks).blocks) {
|
|
90
|
+
for (const n of (node as AstBlocks).blocks) {
|
|
91
|
+
if (checkNode(n, funclist, ctx)) {
|
|
92
|
+
return true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import { NakoLogger } from './nako_logger.mjs'
|
|
3
3
|
import { FuncList, FuncListItem, SourceMap, NewEmptyToken, ExportMap } from './nako_types.mjs'
|
|
4
|
-
import { Ast
|
|
4
|
+
import { Ast } from './nako_ast.mjs'
|
|
5
5
|
import { Token, TokenType } from './nako_token.mjs'
|
|
6
|
+
import { nodeToStr } from './nako_parser_message.mjs'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* なでしこの構文解析のためのユーティリティクラス
|
|
@@ -31,7 +32,6 @@ export class NakoParserBase {
|
|
|
31
32
|
protected isReadingCalc: boolean
|
|
32
33
|
protected isExportDefault: boolean
|
|
33
34
|
protected isExportStack: boolean[]
|
|
34
|
-
protected isModifiedNodes: boolean
|
|
35
35
|
|
|
36
36
|
constructor(logger: NakoLogger) {
|
|
37
37
|
this.logger = logger
|
|
@@ -78,7 +78,6 @@ export class NakoParserBase {
|
|
|
78
78
|
this.isExportDefault = true
|
|
79
79
|
this.isExportStack = []
|
|
80
80
|
this.moduleExport = new Map()
|
|
81
|
-
this.isModifiedNodes = false
|
|
82
81
|
|
|
83
82
|
this.init()
|
|
84
83
|
}
|
|
@@ -110,7 +109,6 @@ export class NakoParserBase {
|
|
|
110
109
|
this.arrayIndexFrom = 0
|
|
111
110
|
this.flagReverseArrayIndex = false
|
|
112
111
|
this.flagCheckArrayInit = false
|
|
113
|
-
this.isModifiedNodes = false
|
|
114
112
|
}
|
|
115
113
|
|
|
116
114
|
setFuncList(funclist: FuncList) {
|
|
@@ -359,56 +357,7 @@ export class NakoParserBase {
|
|
|
359
357
|
* @param {boolean} debugMode
|
|
360
358
|
*/
|
|
361
359
|
nodeToStr(node: Ast|Token|null, opts: {depth: number, typeName?: string}, debugMode: boolean): string {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const debug = debugMode ? (' debug: ' + JSON.stringify(node, null, 2)) : ''
|
|
365
|
-
if (!node) { return '(NULL)' }
|
|
366
|
-
switch (node.type) {
|
|
367
|
-
case 'not':
|
|
368
|
-
if (depth >= 0) {
|
|
369
|
-
const subNode: Ast = (node as AstBlocks).blocks[0]
|
|
370
|
-
return `${typeName('')}『${this.nodeToStr(subNode, { depth }, debugMode)}に演算子『not』を適用した式${debug}』`
|
|
371
|
-
} else {
|
|
372
|
-
return `${typeName('演算子')}『not』`
|
|
373
|
-
}
|
|
374
|
-
case 'op': {
|
|
375
|
-
const node2: AstOperator = node as AstOperator
|
|
376
|
-
let operator: string = node2.operator || ''
|
|
377
|
-
const table:{[key: string]: string} = { eq: '=', not: '!', gt: '>', lt: '<', and: 'かつ', or: 'または' }
|
|
378
|
-
if (operator in table) {
|
|
379
|
-
operator = table[operator]
|
|
380
|
-
}
|
|
381
|
-
if (depth >= 0) {
|
|
382
|
-
const left: string = this.nodeToStr(node2.blocks[0], { depth }, debugMode)
|
|
383
|
-
const right: string = this.nodeToStr(node2.blocks[1], { depth }, debugMode)
|
|
384
|
-
if (node2.operator === 'eq') {
|
|
385
|
-
return `${typeName('')}『${left}と${right}が等しいかどうかの比較${debug}』`
|
|
386
|
-
}
|
|
387
|
-
return `${typeName('')}『${left}と${right}に演算子『${operator}』を適用した式${debug}』`
|
|
388
|
-
} else {
|
|
389
|
-
return `${typeName('演算子')}『${operator}${debug}』`
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
case 'number':
|
|
393
|
-
return `${typeName('数値')}${(node as AstConst).value}`
|
|
394
|
-
case 'bigint':
|
|
395
|
-
return `${typeName('巨大整数')}${(node as AstConst).value}`
|
|
396
|
-
case 'string':
|
|
397
|
-
return `${typeName('文字列')}『${(node as AstConst).value}${debug}』`
|
|
398
|
-
case 'word':
|
|
399
|
-
return `${typeName('単語')}『${(node as AstStrValue).value}${debug}』`
|
|
400
|
-
case 'func':
|
|
401
|
-
return `${typeName('関数')}『${node.name || (node as AstStrValue).value}${debug}』`
|
|
402
|
-
case 'eol':
|
|
403
|
-
return '行の末尾'
|
|
404
|
-
case 'eof':
|
|
405
|
-
return 'ファイルの末尾'
|
|
406
|
-
default: {
|
|
407
|
-
let name:any = node.name
|
|
408
|
-
if (name) { name = (node as AstStrValue).value }
|
|
409
|
-
if (typeof name !== 'string') { name = node.type }
|
|
410
|
-
return `${typeName('')}『${name}${debug}』`
|
|
411
|
-
}
|
|
412
|
-
}
|
|
360
|
+
// (実体は nako_parser_message.mts の nodeToStr) #2364
|
|
361
|
+
return nodeToStr(node, opts, debugMode)
|
|
413
362
|
}
|
|
414
363
|
}
|