nadesiko3 3.6.28 → 3.6.31
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/core/package.json +1 -1
- package/core/src/nako_gen.mjs +52 -21
- package/core/src/nako_gen.mts +50 -24
- package/core/src/nako_lex_rules.mjs +5 -2
- package/core/src/nako_lex_rules.mts +5 -2
- package/core/src/nako_lexer.mjs +14 -5
- package/core/src/nako_lexer.mts +14 -5
- package/core/src/nako_parser3.mjs +37 -22
- package/core/src/nako_parser3.mts +36 -22
- package/core/test/basic_test.mjs +13 -0
- package/package.json +1 -1
- package/release/_hash.txt +16 -16
- package/release/_script-tags.txt +33 -33
- package/release/version.js +1 -1
- package/release/version_main.js +1 -1
- package/release/version_main.js.map +1 -1
- package/release/wnako3.js +97 -97
- package/release/wnako3.js.map +3 -3
- package/release/wnako3webworker.js +78 -78
- package/release/wnako3webworker.js.map +3 -3
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser.mjs +16 -1
- package/src/plugin_browser.mts +14 -1
- package/src/plugin_browser_api.mts +1 -0
- package/src/plugin_browser_dom_basic.mjs +117 -0
- package/src/plugin_browser_dom_basic.mts +108 -0
- package/src/plugin_browser_dom_parts.mjs +2 -34
- package/src/plugin_browser_dom_parts.mts +3 -34
- package/tools/nako3edit/html/files.html +7 -5
package/core/package.json
CHANGED
package/core/src/nako_gen.mjs
CHANGED
|
@@ -983,17 +983,6 @@ export class NakoGen {
|
|
|
983
983
|
}
|
|
984
984
|
return code;
|
|
985
985
|
}
|
|
986
|
-
convRefProp(node) {
|
|
987
|
-
const name = this._convGen(node.name, true);
|
|
988
|
-
const list = node.index;
|
|
989
|
-
if (!list || list.length <= 0) {
|
|
990
|
-
throw NakoSyntaxError.fromNode('プロパティがありません。', node);
|
|
991
|
-
}
|
|
992
|
-
const prop = list[0].value;
|
|
993
|
-
const code = `( (function(){ if (${name}.__getProp) { return ${name}.__getProp('${prop}', __self) } ` +
|
|
994
|
-
`else { return ${name}['${prop}'] } })() )`;
|
|
995
|
-
return code;
|
|
996
|
-
}
|
|
997
986
|
convLetArray(node) {
|
|
998
987
|
const id = this.loopId++;
|
|
999
988
|
const valueNode = node.blocks[0];
|
|
@@ -1771,15 +1760,13 @@ export class NakoGen {
|
|
|
1771
1760
|
if (!node.blocks || node.blocks.length == 0) {
|
|
1772
1761
|
throw NakoSyntaxError.fromNode('代入する値がありません。', node);
|
|
1773
1762
|
}
|
|
1774
|
-
const
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
if (astProp) {
|
|
1778
|
-
prop = astProp.value;
|
|
1779
|
-
}
|
|
1780
|
-
else {
|
|
1763
|
+
const propList = node.index;
|
|
1764
|
+
const propTopAst = propList.pop();
|
|
1765
|
+
if (propTopAst === undefined) {
|
|
1781
1766
|
throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node);
|
|
1782
1767
|
}
|
|
1768
|
+
const propTop = (typeof propTopAst.value === 'string') ? propTopAst.value : '';
|
|
1769
|
+
const astValue = node.blocks[0];
|
|
1783
1770
|
let value = null;
|
|
1784
1771
|
// 値のプログラムを生成
|
|
1785
1772
|
if (astValue) {
|
|
@@ -1796,12 +1783,56 @@ export class NakoGen {
|
|
|
1796
1783
|
if (res === null) {
|
|
1797
1784
|
throw NakoSyntaxError.fromNode(`変数『${name}』が見当たりません。`, node);
|
|
1798
1785
|
}
|
|
1786
|
+
// 変数のプロパティ
|
|
1787
|
+
let nameJs = res.js;
|
|
1788
|
+
if (propList.length > 0) {
|
|
1789
|
+
for (const prop of propList) {
|
|
1790
|
+
if (typeof prop.value === 'string') {
|
|
1791
|
+
nameJs += `['${prop.value}']`;
|
|
1792
|
+
}
|
|
1793
|
+
else {
|
|
1794
|
+
throw NakoSyntaxError.fromNode(`変数『${nameJs}』以下のプロパティにアクセスできません。`, node);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1799
1798
|
// プロパティへの代入式を作る
|
|
1800
|
-
|
|
1801
|
-
code += `
|
|
1802
|
-
code += `else { ${propVar} = ${value} };`;
|
|
1799
|
+
code += `if (typeof ${nameJs}.__setProp === 'function') { ${nameJs}.__setProp('${propTop}', ${value}, __self); } `;
|
|
1800
|
+
code += `else { ${nameJs}['${propTop}'] = ${value} };`;
|
|
1803
1801
|
return ';' + this.convLineno(node, false) + code + '\n';
|
|
1804
1802
|
}
|
|
1803
|
+
// プロパティへの参照 (#1793)
|
|
1804
|
+
convRefProp(node) {
|
|
1805
|
+
const name = this._convGen(node.name, true);
|
|
1806
|
+
const list = node.index;
|
|
1807
|
+
if (!list || list.length <= 0) {
|
|
1808
|
+
throw NakoSyntaxError.fromNode('プロパティがありません。', node);
|
|
1809
|
+
}
|
|
1810
|
+
let code;
|
|
1811
|
+
const propList = list;
|
|
1812
|
+
if (propList.length <= 1) {
|
|
1813
|
+
const propKey = propList[0].value;
|
|
1814
|
+
const code_call = `${name}.__getProp('${propKey}', __self)`;
|
|
1815
|
+
const code_prop = `${name}['${propKey}']`;
|
|
1816
|
+
const code_if = `if (${name}.__getProp) { return ${code_call} } else { return ${code_prop} }`;
|
|
1817
|
+
code = `( (()=>{ ${code_if} })() )`;
|
|
1818
|
+
}
|
|
1819
|
+
else {
|
|
1820
|
+
const arrs = [];
|
|
1821
|
+
const keys = [];
|
|
1822
|
+
for (let i = 0; i < propList.length; i++) {
|
|
1823
|
+
const propKey = propList[i].value;
|
|
1824
|
+
keys.push(`['${propKey}']`);
|
|
1825
|
+
arrs.push(`'${propKey}'`);
|
|
1826
|
+
}
|
|
1827
|
+
const keyStr = keys.join('');
|
|
1828
|
+
const arrStr = '[' + arrs.join(',') + ']';
|
|
1829
|
+
const code_call = `${name}.__getProp(${arrStr}, __self)`;
|
|
1830
|
+
const code_prop = `${name}${keyStr}`;
|
|
1831
|
+
const code_if = `if (${name}.__getProp) { return ${code_call} } else { return ${code_prop} }`;
|
|
1832
|
+
code = `( (()=>{ ${code_if} })() )`;
|
|
1833
|
+
}
|
|
1834
|
+
return code;
|
|
1835
|
+
}
|
|
1805
1836
|
convDefLocalVar(node) {
|
|
1806
1837
|
const astValue = node.blocks[0];
|
|
1807
1838
|
let value = '0';
|
package/core/src/nako_gen.mts
CHANGED
|
@@ -1059,19 +1059,6 @@ export class NakoGen {
|
|
|
1059
1059
|
return code
|
|
1060
1060
|
}
|
|
1061
1061
|
|
|
1062
|
-
convRefProp (node: Ast): string {
|
|
1063
|
-
const name = this._convGen(node.name as Ast, true)
|
|
1064
|
-
const list: Ast[] | undefined = node.index
|
|
1065
|
-
if (!list || list.length <= 0) {
|
|
1066
|
-
throw NakoSyntaxError.fromNode('プロパティがありません。', node)
|
|
1067
|
-
}
|
|
1068
|
-
const prop = (list[0] as AstStrValue).value
|
|
1069
|
-
const code =
|
|
1070
|
-
`( (function(){ if (${name}.__getProp) { return ${name}.__getProp('${prop}', __self) } ` +
|
|
1071
|
-
`else { return ${name}['${prop}'] } })() )`
|
|
1072
|
-
return code
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
1062
|
convLetArray (node: AstLetArray): string {
|
|
1076
1063
|
const id = this.loopId++
|
|
1077
1064
|
const valueNode: Ast = node.blocks[0]
|
|
@@ -1834,14 +1821,11 @@ export class NakoGen {
|
|
|
1834
1821
|
convLetProp(node: AstLet): string {
|
|
1835
1822
|
if (!node.index || node.index.length == 0) { throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node) }
|
|
1836
1823
|
if (!node.blocks || node.blocks.length == 0) { throw NakoSyntaxError.fromNode('代入する値がありません。', node) }
|
|
1837
|
-
const
|
|
1824
|
+
const propList = node.index as AstStrValue[]
|
|
1825
|
+
const propTopAst = propList.pop()
|
|
1826
|
+
if (propTopAst === undefined) { throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node) }
|
|
1827
|
+
const propTop = (typeof propTopAst.value === 'string') ? propTopAst.value : ''
|
|
1838
1828
|
const astValue = node.blocks[0]
|
|
1839
|
-
let prop = ''
|
|
1840
|
-
if (astProp) {
|
|
1841
|
-
prop = (astProp as AstStrValue).value
|
|
1842
|
-
} else {
|
|
1843
|
-
throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node)
|
|
1844
|
-
}
|
|
1845
1829
|
let value = null
|
|
1846
1830
|
// 値のプログラムを生成
|
|
1847
1831
|
if (astValue) {
|
|
@@ -1849,7 +1833,6 @@ export class NakoGen {
|
|
|
1849
1833
|
} else {
|
|
1850
1834
|
throw NakoSyntaxError.fromNode('代入する値がありません。', node)
|
|
1851
1835
|
}
|
|
1852
|
-
|
|
1853
1836
|
// 変数名
|
|
1854
1837
|
const name: string = node.name
|
|
1855
1838
|
const res = this.findVar(name, value)
|
|
@@ -1858,12 +1841,55 @@ export class NakoGen {
|
|
|
1858
1841
|
if (res === null) {
|
|
1859
1842
|
throw NakoSyntaxError.fromNode(`変数『${name}』が見当たりません。`, node)
|
|
1860
1843
|
}
|
|
1844
|
+
// 変数のプロパティ
|
|
1845
|
+
let nameJs = res.js
|
|
1846
|
+
if (propList.length > 0) {
|
|
1847
|
+
for (const prop of propList) {
|
|
1848
|
+
if (typeof prop.value === 'string') {
|
|
1849
|
+
nameJs += `['${prop.value}']`
|
|
1850
|
+
} else {
|
|
1851
|
+
throw NakoSyntaxError.fromNode(
|
|
1852
|
+
`変数『${nameJs}』以下のプロパティにアクセスできません。`, node)
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1861
1856
|
// プロパティへの代入式を作る
|
|
1862
|
-
|
|
1863
|
-
code += `
|
|
1864
|
-
code += `else { ${propVar} = ${value} };`
|
|
1857
|
+
code += `if (typeof ${nameJs}.__setProp === 'function') { ${nameJs}.__setProp('${propTop}', ${value}, __self); } `
|
|
1858
|
+
code += `else { ${nameJs}['${propTop}'] = ${value} };`
|
|
1865
1859
|
return ';' + this.convLineno(node, false) + code + '\n'
|
|
1866
1860
|
}
|
|
1861
|
+
// プロパティへの参照 (#1793)
|
|
1862
|
+
convRefProp(node: Ast): string {
|
|
1863
|
+
const name = this._convGen(node.name as Ast, true)
|
|
1864
|
+
const list: Ast[] | undefined = node.index
|
|
1865
|
+
if (!list || list.length <= 0) {
|
|
1866
|
+
throw NakoSyntaxError.fromNode('プロパティがありません。', node)
|
|
1867
|
+
}
|
|
1868
|
+
let code
|
|
1869
|
+
const propList = list as AstStrValue[]
|
|
1870
|
+
if (propList.length <= 1) {
|
|
1871
|
+
const propKey = propList[0].value
|
|
1872
|
+
const code_call = `${name}.__getProp('${propKey}', __self)`
|
|
1873
|
+
const code_prop = `${name}['${propKey}']`
|
|
1874
|
+
const code_if = `if (${name}.__getProp) { return ${code_call} } else { return ${code_prop} }`
|
|
1875
|
+
code = `( (()=>{ ${code_if} })() )`
|
|
1876
|
+
} else {
|
|
1877
|
+
const arrs = []
|
|
1878
|
+
const keys = []
|
|
1879
|
+
for (let i = 0; i < propList.length; i++) {
|
|
1880
|
+
const propKey = propList[i].value
|
|
1881
|
+
keys.push(`['${propKey}']`)
|
|
1882
|
+
arrs.push(`'${propKey}'`)
|
|
1883
|
+
}
|
|
1884
|
+
const keyStr = keys.join('')
|
|
1885
|
+
const arrStr = '[' + arrs.join(',') + ']'
|
|
1886
|
+
const code_call = `${name}.__getProp(${arrStr}, __self)`
|
|
1887
|
+
const code_prop = `${name}${keyStr}`
|
|
1888
|
+
const code_if = `if (${name}.__getProp) { return ${code_call} } else { return ${code_prop} }`
|
|
1889
|
+
code = `( (()=>{ ${code_if} })() )`
|
|
1890
|
+
}
|
|
1891
|
+
return code
|
|
1892
|
+
}
|
|
1867
1893
|
|
|
1868
1894
|
convDefLocalVar(node: AstDefVar): string {
|
|
1869
1895
|
const astValue = node.blocks[0]
|
|
@@ -11,7 +11,10 @@ const wordSpecial = /^(かつ|または)/;
|
|
|
11
11
|
const errorRead = (ch) => {
|
|
12
12
|
return function () { throw new Error('突然の『' + ch + '』があります。'); };
|
|
13
13
|
};
|
|
14
|
-
|
|
14
|
+
// 数値の後の単位は自動的に省略されるルール (#994)
|
|
15
|
+
export const unitRE = /^(円|ドル|元|歩|㎡|坪|度|℃|°|個|つ|本|冊|才|歳|匹|枚|皿|セット|羽|人|件|行|列|機|品|m|mm|cm|km|g|kg|t|b|mb|kb|gb)/;
|
|
16
|
+
// CSSの単位であれば自動的に文字列に変換するルール (#1811)
|
|
17
|
+
export const cssUnitRE = /^(px|em|ex|rem|vw|vh|vmin|vmax)/;
|
|
15
18
|
/** トークンに区切るルールの一覧 */
|
|
16
19
|
export const rules = [
|
|
17
20
|
// 上から順にマッチさせていく
|
|
@@ -81,7 +84,7 @@ export const rules = [
|
|
|
81
84
|
{ name: ')', pattern: /^\)/, readJosi: true },
|
|
82
85
|
{ name: '|', pattern: /^\|/ },
|
|
83
86
|
{ name: '??', pattern: /^\?\?/ }, // 「表示」のエイリアス #1745
|
|
84
|
-
{ name: '$', pattern:
|
|
87
|
+
{ name: '$', pattern: /^(\$|\.)/ }, // プロパティアクセス (#1793)(#1807)
|
|
85
88
|
{ name: 'string', pattern: /^🌿/, cbParser: src => cbString('🌿', '🌿', src) },
|
|
86
89
|
{ name: 'string_ex', pattern: /^🌴/, cbParser: src => cbString('🌴', '🌴', src) },
|
|
87
90
|
{ name: 'string_ex', pattern: /^「/, cbParser: src => cbString('「', '」', src) },
|
|
@@ -15,7 +15,10 @@ const errorRead = (ch: string): any => {
|
|
|
15
15
|
return function () { throw new Error('突然の『' + ch + '』があります。') }
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// 数値の後の単位は自動的に省略されるルール (#994)
|
|
19
|
+
export const unitRE = /^(円|ドル|元|歩|㎡|坪|度|℃|°|個|つ|本|冊|才|歳|匹|枚|皿|セット|羽|人|件|行|列|機|品|m|mm|cm|km|g|kg|t|b|mb|kb|gb)/
|
|
20
|
+
// CSSの単位であれば自動的に文字列に変換するルール (#1811)
|
|
21
|
+
export const cssUnitRE = /^(px|em|ex|rem|vw|vh|vmin|vmax)/
|
|
19
22
|
|
|
20
23
|
export interface NakoLexParseResult {
|
|
21
24
|
src: string;
|
|
@@ -101,7 +104,7 @@ export const rules: NakoLexRule[] = [
|
|
|
101
104
|
{ name: ')', pattern: /^\)/, readJosi: true },
|
|
102
105
|
{ name: '|', pattern: /^\|/ },
|
|
103
106
|
{ name: '??', pattern: /^\?\?/ }, // 「表示」のエイリアス #1745
|
|
104
|
-
{ name: '$', pattern:
|
|
107
|
+
{ name: '$', pattern: /^(\$|\.)/ }, // プロパティアクセス (#1793)(#1807)
|
|
105
108
|
{ name: 'string', pattern: /^🌿/, cbParser: src => cbString('🌿', '🌿', src) },
|
|
106
109
|
{ name: 'string_ex', pattern: /^🌴/, cbParser: src => cbString('🌴', '🌴', src) },
|
|
107
110
|
{ name: 'string_ex', pattern: /^「/, cbParser: src => cbString('「', '」', src) },
|
package/core/src/nako_lexer.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { isIndentChars } from './nako_indent_chars.mjs';
|
|
|
10
10
|
// 助詞の一覧
|
|
11
11
|
import { josiRE, removeJosiMap, tararebaMap, josiListExport } from './nako_josi_list.mjs';
|
|
12
12
|
// 字句解析ルールの一覧
|
|
13
|
-
import { rules, unitRE } from './nako_lex_rules.mjs';
|
|
13
|
+
import { rules, unitRE, cssUnitRE } from './nako_lex_rules.mjs';
|
|
14
14
|
import { NakoLexerError, InternalLexerError } from './nako_errors.mjs';
|
|
15
15
|
export class NakoLexer {
|
|
16
16
|
/**
|
|
@@ -578,6 +578,7 @@ export class NakoLexer {
|
|
|
578
578
|
if (!m) {
|
|
579
579
|
continue;
|
|
580
580
|
}
|
|
581
|
+
let ruleName = rule.name;
|
|
581
582
|
ok = true;
|
|
582
583
|
// 空白ならスキップ
|
|
583
584
|
if (rule.name === 'space') {
|
|
@@ -676,6 +677,14 @@ export class NakoLexer {
|
|
|
676
677
|
src = src.substring(um[0].length);
|
|
677
678
|
column += m[0].length;
|
|
678
679
|
}
|
|
680
|
+
// CSSの単位なら自動的に文字列として認識させる #1811
|
|
681
|
+
const cssUnit = cssUnitRE.exec(src);
|
|
682
|
+
if (cssUnit) {
|
|
683
|
+
ruleName = 'string';
|
|
684
|
+
src = src.substring(cssUnit[0].length);
|
|
685
|
+
column += m[0].length;
|
|
686
|
+
value += cssUnit[0];
|
|
687
|
+
}
|
|
679
688
|
}
|
|
680
689
|
let josi = '';
|
|
681
690
|
if (rule.readJosi) {
|
|
@@ -699,7 +708,7 @@ export class NakoLexer {
|
|
|
699
708
|
}
|
|
700
709
|
}
|
|
701
710
|
}
|
|
702
|
-
switch (
|
|
711
|
+
switch (ruleName) {
|
|
703
712
|
case 'def_test': {
|
|
704
713
|
isDefTest = true;
|
|
705
714
|
break;
|
|
@@ -713,12 +722,12 @@ export class NakoLexer {
|
|
|
713
722
|
}
|
|
714
723
|
}
|
|
715
724
|
// ここまで‰(#682) を処理
|
|
716
|
-
if (
|
|
725
|
+
if (ruleName === 'dec_lineno') {
|
|
717
726
|
line--;
|
|
718
727
|
continue;
|
|
719
728
|
}
|
|
720
729
|
result.push({
|
|
721
|
-
type:
|
|
730
|
+
type: ruleName,
|
|
722
731
|
value,
|
|
723
732
|
indent,
|
|
724
733
|
line: lineCurrent,
|
|
@@ -729,7 +738,7 @@ export class NakoLexer {
|
|
|
729
738
|
preprocessedCodeLength: (srcLength - src.length) - srcOffset
|
|
730
739
|
});
|
|
731
740
|
// 改行のとき次の行のインデントを調べる。なお、改行の後は必ずcolumnが1になる。インデント構文のため、一行に2つ以上の文を含むときを考慮する。(core #66)
|
|
732
|
-
if (
|
|
741
|
+
if (ruleName === 'eol' && column === 1) {
|
|
733
742
|
const ia = this.countIndent(src);
|
|
734
743
|
indent = ia[0];
|
|
735
744
|
column += ia[1];
|
package/core/src/nako_lexer.mts
CHANGED
|
@@ -14,7 +14,7 @@ import { isIndentChars } from './nako_indent_chars.mjs'
|
|
|
14
14
|
import { josiRE, removeJosiMap, tararebaMap, josiListExport } from './nako_josi_list.mjs'
|
|
15
15
|
|
|
16
16
|
// 字句解析ルールの一覧
|
|
17
|
-
import { rules, unitRE, NakoLexParseResult } from './nako_lex_rules.mjs'
|
|
17
|
+
import { rules, unitRE, cssUnitRE, NakoLexParseResult } from './nako_lex_rules.mjs'
|
|
18
18
|
import { NakoLexerError, InternalLexerError } from './nako_errors.mjs'
|
|
19
19
|
|
|
20
20
|
import { FuncList, FuncArgs, ExportMap, FuncListItem } from './nako_types.mjs'
|
|
@@ -563,6 +563,7 @@ export class NakoLexer {
|
|
|
563
563
|
// 正規表現でマッチ
|
|
564
564
|
const m = rule.pattern.exec(src)
|
|
565
565
|
if (!m) { continue }
|
|
566
|
+
let ruleName = rule.name
|
|
566
567
|
ok = true
|
|
567
568
|
// 空白ならスキップ
|
|
568
569
|
if (rule.name === 'space') {
|
|
@@ -673,6 +674,14 @@ export class NakoLexer {
|
|
|
673
674
|
src = src.substring(um[0].length)
|
|
674
675
|
column += m[0].length
|
|
675
676
|
}
|
|
677
|
+
// CSSの単位なら自動的に文字列として認識させる #1811
|
|
678
|
+
const cssUnit = cssUnitRE.exec(src)
|
|
679
|
+
if (cssUnit) {
|
|
680
|
+
ruleName = 'string'
|
|
681
|
+
src = src.substring(cssUnit[0].length)
|
|
682
|
+
column += m[0].length
|
|
683
|
+
value += cssUnit[0]
|
|
684
|
+
}
|
|
676
685
|
}
|
|
677
686
|
|
|
678
687
|
let josi = ''
|
|
@@ -696,7 +705,7 @@ export class NakoLexer {
|
|
|
696
705
|
}
|
|
697
706
|
}
|
|
698
707
|
|
|
699
|
-
switch (
|
|
708
|
+
switch (ruleName) {
|
|
700
709
|
case 'def_test': {
|
|
701
710
|
isDefTest = true
|
|
702
711
|
break
|
|
@@ -710,13 +719,13 @@ export class NakoLexer {
|
|
|
710
719
|
}
|
|
711
720
|
}
|
|
712
721
|
// ここまで‰(#682) を処理
|
|
713
|
-
if (
|
|
722
|
+
if (ruleName === 'dec_lineno') {
|
|
714
723
|
line--
|
|
715
724
|
continue
|
|
716
725
|
}
|
|
717
726
|
|
|
718
727
|
result.push({
|
|
719
|
-
type:
|
|
728
|
+
type: ruleName,
|
|
720
729
|
value,
|
|
721
730
|
indent,
|
|
722
731
|
line: lineCurrent,
|
|
@@ -727,7 +736,7 @@ export class NakoLexer {
|
|
|
727
736
|
preprocessedCodeLength: (srcLength - src.length) - srcOffset
|
|
728
737
|
})
|
|
729
738
|
// 改行のとき次の行のインデントを調べる。なお、改行の後は必ずcolumnが1になる。インデント構文のため、一行に2つ以上の文を含むときを考慮する。(core #66)
|
|
730
|
-
if (
|
|
739
|
+
if (ruleName === 'eol' && column === 1) {
|
|
731
740
|
const ia = this.countIndent(src)
|
|
732
741
|
indent = ia[0]
|
|
733
742
|
column += ia[1]
|
|
@@ -1789,25 +1789,34 @@ export class NakoParser extends NakoParserBase {
|
|
|
1789
1789
|
throw NakoSyntaxError.fromNode(`${this.nodeToStr(word, { depth: 1 }, false)}への代入文で計算式に以下の書き間違いがあります。\n${err.message}`, map);
|
|
1790
1790
|
}
|
|
1791
1791
|
}
|
|
1792
|
-
//
|
|
1793
|
-
if (this.check2(['word', '$', 'word', 'eq']) || this.check2(['word', '$', '
|
|
1794
|
-
const
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
const
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
blocks: [valueToken],
|
|
1804
|
-
josi: '',
|
|
1805
|
-
...map,
|
|
1806
|
-
end: this.peekSourceMap()
|
|
1807
|
-
};
|
|
1792
|
+
// オブジェクトプロパティ構文 代入文 (#1793)
|
|
1793
|
+
if (this.check2(['word', '$', '*', '$', '*', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', 'eq'])) {
|
|
1794
|
+
const propList = [];
|
|
1795
|
+
const word = this.getVarName(this.get());
|
|
1796
|
+
for (;;) {
|
|
1797
|
+
const flag = this.peek();
|
|
1798
|
+
if (flag === null || flag.type !== '$') {
|
|
1799
|
+
break;
|
|
1800
|
+
}
|
|
1801
|
+
this.get(); // skip $
|
|
1802
|
+
propList.push(this.get()); // property
|
|
1808
1803
|
}
|
|
1809
|
-
|
|
1804
|
+
this.get(); // skip eq
|
|
1805
|
+
const valueToken = this.yCalc(); // calc
|
|
1806
|
+
if (valueToken === null) {
|
|
1807
|
+
throw NakoSyntaxError.fromNode(`${this.nodeToStr(word, { depth: 1 }, false)}への代入文の計算式に書き間違いがあります。`, map);
|
|
1808
|
+
}
|
|
1809
|
+
return {
|
|
1810
|
+
type: 'let_prop',
|
|
1811
|
+
name: word.value,
|
|
1812
|
+
index: propList,
|
|
1813
|
+
blocks: [valueToken],
|
|
1814
|
+
josi: '',
|
|
1815
|
+
...map,
|
|
1816
|
+
end: this.peekSourceMap()
|
|
1817
|
+
};
|
|
1810
1818
|
}
|
|
1819
|
+
// オブジェクトプロパティ構文 ここまで
|
|
1811
1820
|
// let_array ?
|
|
1812
1821
|
if (this.check2(['word', '@'])) {
|
|
1813
1822
|
const la = this.yLetArrayAt(map);
|
|
@@ -2600,15 +2609,21 @@ export class NakoParser extends NakoParserBase {
|
|
|
2600
2609
|
}
|
|
2601
2610
|
return ast;
|
|
2602
2611
|
}
|
|
2603
|
-
// word$prop
|
|
2612
|
+
// オブジェクトプロパティ構文(参照) word$prop (#1793)
|
|
2604
2613
|
if (word.josi === '' && (this.check2(['$', 'word']) || this.check2(['$', 'string']))) {
|
|
2605
|
-
|
|
2606
|
-
|
|
2614
|
+
const propList = [];
|
|
2615
|
+
let josi = '';
|
|
2616
|
+
while (this.check('$')) {
|
|
2617
|
+
this.get(); // skip '$'
|
|
2618
|
+
const prop = this.get();
|
|
2619
|
+
propList.push(prop);
|
|
2620
|
+
josi = prop.josi;
|
|
2621
|
+
}
|
|
2607
2622
|
return {
|
|
2608
2623
|
type: 'ref_prop', // プロパティ参照
|
|
2609
2624
|
name: word,
|
|
2610
|
-
index:
|
|
2611
|
-
josi:
|
|
2625
|
+
index: propList,
|
|
2626
|
+
josi: josi,
|
|
2612
2627
|
...map,
|
|
2613
2628
|
end: this.peekSourceMap()
|
|
2614
2629
|
};
|
|
@@ -1556,25 +1556,33 @@ export class NakoParser extends NakoParserBase {
|
|
|
1556
1556
|
throw NakoSyntaxError.fromNode(`${this.nodeToStr(word, { depth: 1 }, false)}への代入文で計算式に以下の書き間違いがあります。\n${err.message}`, map)
|
|
1557
1557
|
}
|
|
1558
1558
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
index: [propToken],
|
|
1570
|
-
blocks: [valueToken],
|
|
1571
|
-
josi: '',
|
|
1572
|
-
...map,
|
|
1573
|
-
end: this.peekSourceMap()
|
|
1574
|
-
} as AstLet
|
|
1559
|
+
|
|
1560
|
+
// オブジェクトプロパティ構文 代入文 (#1793)
|
|
1561
|
+
if (this.check2(['word', '$', '*', '$', '*', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', '$', '*', 'eq']) || this.check2(['word', '$', '*', 'eq'])) {
|
|
1562
|
+
const propList = []
|
|
1563
|
+
const word = this.getVarName(this.get() as Token)
|
|
1564
|
+
for (;;) {
|
|
1565
|
+
const flag = this.peek()
|
|
1566
|
+
if (flag === null || flag.type !== '$') { break }
|
|
1567
|
+
this.get() // skip $
|
|
1568
|
+
propList.push(this.get() as Ast) // property
|
|
1575
1569
|
}
|
|
1576
|
-
|
|
1570
|
+
this.get() // skip eq
|
|
1571
|
+
const valueToken = this.yCalc() // calc
|
|
1572
|
+
if (valueToken === null) {
|
|
1573
|
+
throw NakoSyntaxError.fromNode(`${this.nodeToStr(word, { depth: 1 }, false)}への代入文の計算式に書き間違いがあります。`, map)
|
|
1574
|
+
}
|
|
1575
|
+
return {
|
|
1576
|
+
type: 'let_prop',
|
|
1577
|
+
name: (word as AstStrValue).value,
|
|
1578
|
+
index: propList,
|
|
1579
|
+
blocks: [valueToken],
|
|
1580
|
+
josi: '',
|
|
1581
|
+
...map,
|
|
1582
|
+
end: this.peekSourceMap()
|
|
1583
|
+
} as AstLet
|
|
1577
1584
|
}
|
|
1585
|
+
// オブジェクトプロパティ構文 ここまで
|
|
1578
1586
|
|
|
1579
1587
|
// let_array ?
|
|
1580
1588
|
if (this.check2(['word', '@'])) {
|
|
@@ -2311,15 +2319,21 @@ export class NakoParser extends NakoParserBase {
|
|
|
2311
2319
|
return ast
|
|
2312
2320
|
}
|
|
2313
2321
|
|
|
2314
|
-
// word$prop
|
|
2322
|
+
// オブジェクトプロパティ構文(参照) word$prop (#1793)
|
|
2315
2323
|
if (word.josi === '' && (this.check2(['$', 'word']) || this.check2(['$', 'string']))) {
|
|
2316
|
-
|
|
2317
|
-
|
|
2324
|
+
const propList: Ast[] = []
|
|
2325
|
+
let josi = ''
|
|
2326
|
+
while (this.check('$')) {
|
|
2327
|
+
this.get() // skip '$'
|
|
2328
|
+
const prop = this.get() as Token
|
|
2329
|
+
propList.push(prop as Ast)
|
|
2330
|
+
josi = prop.josi
|
|
2331
|
+
}
|
|
2318
2332
|
return {
|
|
2319
2333
|
type: 'ref_prop', // プロパティ参照
|
|
2320
2334
|
name: word,
|
|
2321
|
-
index:
|
|
2322
|
-
josi:
|
|
2335
|
+
index: propList,
|
|
2336
|
+
josi: josi,
|
|
2323
2337
|
...map,
|
|
2324
2338
|
end: this.peekSourceMap()
|
|
2325
2339
|
}
|
package/core/test/basic_test.mjs
CHANGED
|
@@ -376,6 +376,10 @@ describe('basic', async () => {
|
|
|
376
376
|
await cmp('A={"幅":30};A$幅=50;A$幅を表示', '50')
|
|
377
377
|
await cmp('A={"高":30};A$高さ=50;A$高さを表示', '50') // 送り仮名の省略
|
|
378
378
|
})
|
|
379
|
+
it('オブジェクトを手軽に設定する-ドットアクセス(#1807)', async () => {
|
|
380
|
+
await cmp('A={"高":30};A.高=50;A.高を表示', '50') //
|
|
381
|
+
await cmp('A={"A":30,"B":50};A.A=500;A.Aを表示', '500') //
|
|
382
|
+
})
|
|
379
383
|
it('オブジェクトを手軽に設定する-プロパティ関数(#1793)', async () => {
|
|
380
384
|
// プロパティの値を取得して10倍にして返す
|
|
381
385
|
await cmp(
|
|
@@ -394,4 +398,13 @@ describe('basic', async () => {
|
|
|
394
398
|
await cmp('A={"幅":30};A$"幅"=50;A$"幅"を表示', '50')
|
|
395
399
|
await cmp('A={"高":30};A$"高"=50;A$"高"を表示', '50') // 送り仮名の省略
|
|
396
400
|
})
|
|
401
|
+
it('オブジェクトプロパティ構文$でネスト可能にする #1805', async () => {
|
|
402
|
+
await cmp('A={"スタイル":{"幅":300}};A$スタイル$幅=1;A$スタイル$幅を表示', '1')
|
|
403
|
+
await cmp('A={"猫":{"三毛猫":1, "日本猫":2}};A$猫$日本猫=123;A$猫$日本猫を表示', '123')
|
|
404
|
+
})
|
|
405
|
+
it('CSSの単位付き数値を文字列として認識させる #1811', async () => {
|
|
406
|
+
await cmp('(TYPEOF(30px))を表示', 'string')
|
|
407
|
+
await cmp('A=30em;Aを表示', '30em')
|
|
408
|
+
await cmp('A=30px;AをJSONエンコードして表示', '"30px"')
|
|
409
|
+
})
|
|
397
410
|
})
|
package/package.json
CHANGED
package/release/_hash.txt
CHANGED
|
@@ -144,22 +144,22 @@ wnako3webworker.js:
|
|
|
144
144
|
sha256(base64): zkHQ1vYOjoH4nffi+OulPeq/tql28XhdNuKpcaBCOKk=
|
|
145
145
|
sha512(base64): cY0Mzrpoz/uEyY1n8MeJeWdDmm9vqI7dh28wEqJGtVRfYOJvDHiYDzzlfGndOWmzZmHUK6ZAE7YaUJ7zZxiZLw==
|
|
146
146
|
version.js:
|
|
147
|
-
md5(hex):
|
|
148
|
-
sha256(hex):
|
|
149
|
-
sha256(base64):
|
|
150
|
-
sha512(base64):
|
|
147
|
+
md5(hex): f1362234962d1c50afbf9ce0aa23b7bc
|
|
148
|
+
sha256(hex): 9f7edac2f464dafd23f9cb9987936dd49c3c8c03429ac68da7493600d1c75f37
|
|
149
|
+
sha256(base64): n37awvRk2v0j+cuZh5Nt1Jw8jANCmsaNp0k2ANHHXzc=
|
|
150
|
+
sha512(base64): 0pMDIH7fqnXdu8+pGcl0z02O5rAzDFNzi2/j5E3N9kVMiNjwysNoaNzDVMTn7aBWF3c7JG1Pfb6Cz3aibNsp6Q==
|
|
151
151
|
version_main.js:
|
|
152
|
-
md5(hex):
|
|
153
|
-
sha256(hex):
|
|
154
|
-
sha256(base64):
|
|
155
|
-
sha512(base64):
|
|
152
|
+
md5(hex): f1362234962d1c50afbf9ce0aa23b7bc
|
|
153
|
+
sha256(hex): 9f7edac2f464dafd23f9cb9987936dd49c3c8c03429ac68da7493600d1c75f37
|
|
154
|
+
sha256(base64): n37awvRk2v0j+cuZh5Nt1Jw8jANCmsaNp0k2ANHHXzc=
|
|
155
|
+
sha512(base64): 0pMDIH7fqnXdu8+pGcl0z02O5rAzDFNzi2/j5E3N9kVMiNjwysNoaNzDVMTn7aBWF3c7JG1Pfb6Cz3aibNsp6Q==
|
|
156
156
|
wnako3.js:
|
|
157
|
-
md5(hex):
|
|
158
|
-
sha256(hex):
|
|
159
|
-
sha256(base64):
|
|
160
|
-
sha512(base64):
|
|
157
|
+
md5(hex): 2692c3fd365c8a3ff9a9d206af81000d
|
|
158
|
+
sha256(hex): 6324461eda1bbb9c5a4c7b6e5df90908f5e76a4cfdd14c83dc751e2534b0a9e3
|
|
159
|
+
sha256(base64): YyRGHtobu5xaTHtuXfkJCPXnakz90UyD3HUeJTSwqeM=
|
|
160
|
+
sha512(base64): r3o8nwLwABlWtdoD7i/tH/mzlYMw6fGDrSa6I/OYtilRaDnU/SpeROmVLwN+O5bEXAsdr+r6o5DQyafwG7HVrA==
|
|
161
161
|
wnako3webworker.js:
|
|
162
|
-
md5(hex):
|
|
163
|
-
sha256(hex):
|
|
164
|
-
sha256(base64):
|
|
165
|
-
sha512(base64):
|
|
162
|
+
md5(hex): a7293f17a0350d541c40e563c69f71a1
|
|
163
|
+
sha256(hex): 38cbb6088ee124c3b36b20db3c1b8d7c4cd65b2b7914483817c63e150305b8fe
|
|
164
|
+
sha256(base64): OMu2CI7hJMOzayDbPBuNfEzWWyt5FEg4F8Y+FQMFuP4=
|
|
165
|
+
sha512(base64): 6WCJv1QD9Q0zjq6r46XBxw+YAkJGID0G8kY8RgP3OZF5WD5s4aDnomf6UqSUi9HL0vdtpi1WfzruoKdo3MSVPg==
|