From 6b0feb597122330c0b6d73e618c013d31a22bbf0 Mon Sep 17 00:00:00 2001 From: kujirahand Date: Sat, 31 Aug 2024 20:53:09 +0900 Subject: [PATCH] =?UTF-8?q?=E6=A7=8B=E6=96=87=E6=9C=A8AST=E3=82=92?= =?UTF-8?q?=E6=95=B4=E7=90=86=E3=81=99=E3=82=8B=20#1742?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/nako_from_dncl.mts | 3 +- core/src/nako_from_dncl2.mts | 4 +- core/src/nako_lex_rules.mts | 4 +- core/src/nako_lexer.mts | 5 +- core/src/nako_parser3.mts | 9 ++- core/src/nako_reserved_words.mts | 6 +- core/src/nako_token.mts | 128 +++++++++++++++++++++++++++++++ core/src/nako_tools.mts | 4 +- core/src/nako_types.mts | 31 +------- 9 files changed, 159 insertions(+), 35 deletions(-) create mode 100644 core/src/nako_token.mts diff --git a/core/src/nako_from_dncl.mts b/core/src/nako_from_dncl.mts index 93c36adb..3e81b16a 100644 --- a/core/src/nako_from_dncl.mts +++ b/core/src/nako_from_dncl.mts @@ -4,6 +4,7 @@ // import { NakoIndentError } from './nako_errors.mjs' import { Token, NewEmptyToken } from './nako_types.mjs' import { joinTokenLines, splitTokens } from './nako_indent_inline.mjs' +import { TokenType } from './nako_token.mjs' // DNCLモードのキーワード const DNCL_KEYWORDS = ['!DNCLモード', '💡DNCLモード'] @@ -183,7 +184,7 @@ export function convertDNCL (tokens: Token[]): Token[] { const t = tokens[i] const a = DNCL_SIMPLES[t.type + ':' + t.value] if (a !== undefined) { - t.type = a[0] + t.type = a[0] as TokenType t.value = a[1] } } diff --git a/core/src/nako_from_dncl2.mts b/core/src/nako_from_dncl2.mts index e8046d88..5a81b9d5 100644 --- a/core/src/nako_from_dncl2.mts +++ b/core/src/nako_from_dncl2.mts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /** * DNCL ver2 に対応する構文 */ @@ -5,6 +6,7 @@ import { Token, NewEmptyToken } from './nako_types.mjs' import { joinTokenLines, splitTokens } from './nako_indent_inline.mjs' import { newToken, debugTokens } from './nako_tools.mjs' +import { TokenType } from './nako_token.mjs' const IS_DEBUG = false const DNCL_ARRAY_INIT_COUNT = 30 @@ -250,7 +252,7 @@ export function convertDNCL2 (tokens: Token[]): Token[] { const t = tokens[i] const a = DNCL_SIMPLES[t.type + ':' + t.value] if (a !== undefined) { - t.type = a[0] + t.type = a[0] as TokenType t.value = a[1] } } diff --git a/core/src/nako_lex_rules.mts b/core/src/nako_lex_rules.mts index d36bc5aa..90511990 100644 --- a/core/src/nako_lex_rules.mts +++ b/core/src/nako_lex_rules.mts @@ -1,8 +1,10 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /** * なでしこ3字句解析のためのルール */ import { josiRE, removeJosiMap } from './nako_josi_list.mjs' +import { TokenType } from './nako_token.mjs' const kanakanji = /^[\u3005\u4E00-\u9FCF_a-zA-Z0-9ァ-ヶー\u2460-\u24FF\u2776-\u277F\u3251-\u32BF]+/ const hira = /^[ぁ-ん]/ @@ -23,7 +25,7 @@ export interface NakoLexParseResult { } export interface NakoLexRule { - name: string; + name: TokenType; pattern: RegExp; readJosi?: boolean; cb?: (v: string) => any; diff --git a/core/src/nako_lexer.mts b/core/src/nako_lexer.mts index 9b2200c2..a1a85a93 100644 --- a/core/src/nako_lexer.mts +++ b/core/src/nako_lexer.mts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ // なでしこの字句解析を行う // 既に全角半角を揃えたコードに対して字句解析を行う import { opPriority } from './nako_parser_const.mjs' @@ -214,7 +215,7 @@ export class NakoLexer { t.value = t.value.substring(0, t.value.length - 1) // N回を挿入 if (!t.endOffset) { t.endOffset = 1 } - const kai = { type: '回', value: '回', indent: t.indent, line: t.line, column: t.column, file: t.file, josi: '', startOffset: t.endOffset - 1, endOffset: t.endOffset, rawJosi: '' } + const kai: Token = { type: '回', value: '回', indent: t.indent, line: t.line, column: t.column, file: t.file, josi: '', startOffset: t.endOffset - 1, endOffset: t.endOffset, rawJosi: '' } tokens.splice(i + 1, 0, kai) t.endOffset-- i++ @@ -458,7 +459,7 @@ export class NakoLexer { if (!t.rawJosi) { t.rawJosi = t.josi } const startOffset = t.endOffset === undefined ? undefined : t.endOffset - t.rawJosi.length tokens.splice(i + 1, 0, { - type: t.josi, + type: 'とは', indent: t.indent, line: t.line, column: t.column, diff --git a/core/src/nako_parser3.mts b/core/src/nako_parser3.mts index 2138f489..cf7f7dbf 100644 --- a/core/src/nako_parser3.mts +++ b/core/src/nako_parser3.mts @@ -897,7 +897,14 @@ export class NakoParser extends NakoParserBase { if (incdec) { if (incdec.type === 'word' && (incdec.value === '増' || incdec.value === '減')) { if (incdec.value === '増') { flagDown = false } - kurikaesu.type = incdec.value + kurikaesu.type // typeを増繰返 | 減繰返 に変換 + const w = incdec.value + kurikaesu.type + if (w == '増繰返') { + kurikaesu.type = '増繰返' + } else if (w == '減繰返') { + kurikaesu.type = '減繰返' + } else { + throw Error('[System Error] 増繰り返し | 減繰り返しのエラー。') + } } else { // 普通の繰り返しの場合 this.stack.push(incdec) // 違ったので改めて追加 diff --git a/core/src/nako_reserved_words.mts b/core/src/nako_reserved_words.mts index b2a229d2..6ed1c8a9 100644 --- a/core/src/nako_reserved_words.mts +++ b/core/src/nako_reserved_words.mts @@ -1,5 +1,8 @@ +import { TokenType } from './nako_token.mjs' + /** 予約語 */ -const reserved: Map = new Map([ +const reserved: Map = new Map([ + ['もし', 'もし'], ['回', '回'], ['回繰返', '回'], // (#924) ['間', '間'], @@ -32,6 +35,7 @@ const reserved: Map = new Map([ ['インデント構文', 'インデント構文'], // https://nadesi.com/v3/doc/go.php?949 ['非同期モード', '非同期モード'], // (#637) ['DNCLモード', 'DNCLモード'], // (#1140) + ['DNCL2モード', 'DNCL2モード'], ['モード設定', 'モード設定'], // (#1020) ['取込', '取込'], ['モジュール公開既定値', 'モジュール公開既定値'], diff --git a/core/src/nako_token.mts b/core/src/nako_token.mts new file mode 100644 index 00000000..1ed1f26a --- /dev/null +++ b/core/src/nako_token.mts @@ -0,0 +1,128 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { FuncListItem, Ast } from './nako_types.mjs' + +export type TokenType = '?' + | 'eol' + | '_eol' + | 'eof' + | 'dec_lineno' + | 'require' + | 'line_comment' | 'range_comment' + | 'とは' // ? + | 'string' | 'string_ex' + | 'number' + | 'word' + | 'ならば' + | '増繰返' | '減繰返' + | '違えば' + | '定数' + | 'ここまで' | 'ここから' + | 'comma' + | 'func' + | 'func_pointer' + | 'not' + | 'code' + | 'space' + | 'def_test' + | 'def_func' + | 'bigint' + | '&' + | '(' + | ')' + | 'eq' + | 'noteq' + | 'gt' + | 'gteq' + | 'lt' + | 'lteq' + | '===' + | '!==' + | '←' + | 'and' + | 'or' + | '@' + | '+' + | '-' + | '*' + | '**' + | '÷' + | '÷÷' + | '^' + | '%' + | '[' + | ']' + | '{' + | '}' + | '|' + | 'shift_r0' + | 'shift_r' + | 'shift_l' + | ':' + | '…' + | 'もし' + | '回' // 回 + | '回' // 回繰返 // (#924) + | '間' // 間 + | '間' // 間繰返 // (#927) + | '繰返' // 繰返 + | '増繰返' // 増繰返 // (#1140) + | '減繰返' // 減繰返 + | '後判定' // 後判定 // (#1147) + | '反復' // 反復 + | '抜ける' // 抜 + | '続ける' // 続 + | '戻る' // 戻 + | '先に' // 先 + | '次に' // 次 + | '代入' // 代入 + | '実行速度優先' // 実行速度優先 + | 'パフォーマンスモニタ適用' // パフォーマンスモニタ適用 // (#986) + | '定める' // 定 + | '逐次実行' // 逐次実行 // 廃止 #1611 ただし念のため残しておく + | '条件分岐' // 条件分岐 + | '増' // 増 + | '減' // 減 + | '変数' // 変数 + | '定数' // 定数 + | 'エラー監視' // エラー監視 // 例外処理:エラーならばと対 + | 'エラー' // エラー + | 'word' // それ + | 'word' // そう // 「それ」のエイリアス + | 'def_func' // 関数 // 無名関数の定義用 + | 'インデント構文' // インデント構文 // https://nadesi.com/v3/doc/go.php?949 + | '非同期モード' // 非同期モード // (#637) + | 'DNCLモード' // DNCLモード // (#1140) + | 'DNCL2モード' + | 'モード設定' // モード設定 // (#1020) + | '取込' // 取込 + | 'モジュール公開既定値' // モジュール公開既定値 + | '厳チェック' // 厳しくチェック (#1698) + | '」' // error - エラーチェックのため + | '』' // error - エラーチェックのため + +// トークン +export interface Token { + type: TokenType; + value: any; + line: number; + column: number; + file: string; + josi: string; + indent: number; + meta?: FuncListItem; + rawJosi?: string; + startOffset?: number | undefined; + endOffset?: number | undefined; + isDefinition?: boolean; + funcPointer?: boolean; + tag?: string; + preprocessedCodeOffset?: number | undefined; + preprocessedCodeLength?: number | undefined; + // eslint-disable-next-line no-use-before-define + name?: Token | Ast; // NakoPaserBase.nodeToStrの問題を回避するため + start?: number; + end?: number; + firstToken?: Token; + lastToken?: Token; +} diff --git a/core/src/nako_tools.mts b/core/src/nako_tools.mts index e4d15619..b7c3249c 100644 --- a/core/src/nako_tools.mts +++ b/core/src/nako_tools.mts @@ -1,7 +1,9 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /** * よく使う処理をまとめたもの */ import { Token, NewEmptyToken } from './nako_types.mjs' +import { TokenType } from './nako_token.mjs' /** * トークンの内容をデバッグ出力する関数 @@ -37,7 +39,7 @@ export function makeIndent (n: number): string { } let lastTokenInfo = NewEmptyToken() -export function newToken (type: string, value: any, templateToken: Token|undefined = undefined): Token { +export function newToken (type: TokenType, value: any, templateToken: Token|undefined = undefined): Token { if (templateToken) { lastTokenInfo = templateToken } diff --git a/core/src/nako_types.mts b/core/src/nako_types.mts index 43929de7..4cedcd88 100644 --- a/core/src/nako_types.mts +++ b/core/src/nako_types.mts @@ -5,13 +5,16 @@ import { NakoGlobal } from './nako_global.mjs' import { Ast as AstRaw } from './nako_ast.mjs' +import { Token as TokenRaw, TokenType } from './nako_token.mjs' export type Ast = AstRaw; +export type Token = TokenRaw; // 関数に関する定義 export type FuncArgs = string[][] export type FuncListItemType = 'func' | 'var' | 'const' | 'test_func' + // FuncListの定義 export interface FuncListItem { type: FuncListItemType; @@ -43,33 +46,7 @@ export interface TokenMeta { funcPointers: any[] | undefined; } -// トークン -export interface Token { - type: string; - value: any; - line: number; - column: number; - file: string; - josi: string; - indent: number; - meta?: FuncListItem; - rawJosi?: string; - startOffset?: number | undefined; - endOffset?: number | undefined; - isDefinition?: boolean; - funcPointer?: boolean; - tag?: string; - preprocessedCodeOffset?: number | undefined; - preprocessedCodeLength?: number | undefined; - // eslint-disable-next-line no-use-before-define - name?: Token | Ast; // NakoPaserBase.nodeToStrの問題を回避するため - start?: number; - end?: number; - firstToken?: Token; - lastToken?: Token; -} - -export function NewEmptyToken (type = '?', value: any = '', indent = -1, line = 0, file = 'main.nako3'): Token { +export function NewEmptyToken(type: TokenType = '?', value: any = '', indent = -1, line = 0, file = 'main.nako3'): Token { return { type, value,