@fluxion-ui/compiler-nui 0.0.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026-present, Fluxion Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("@fluxion-ui/compiler-core"),n=require("@fluxion-ui/compiler-dom"),t=(e=>(e[e.INDENT=0]="INDENT",e[e.DEDENT=1]="DEDENT",e[e.NEWLINE=2]="NEWLINE",e[e.EOF=3]="EOF",e[e.IDENTIFIER=4]="IDENTIFIER",e[e.STRING=5]="STRING",e[e.NUMBER=6]="NUMBER",e[e.IMPORT=7]="IMPORT",e[e.FROM=8]="FROM",e[e.FUNCTION=9]="FUNCTION",e[e.IF=10]="IF",e[e.ELIF=11]="ELIF",e[e.ELSE=12]="ELSE",e[e.FOR=13]="FOR",e[e.IN=14]="IN",e[e.VIEW=15]="VIEW",e[e.STYLE=16]="STYLE",e[e.SIGNAL=17]="SIGNAL",e[e.ASYNC_SIGNAL=18]="ASYNC_SIGNAL",e[e.EQUALS=19]="EQUALS",e[e.COMMA=20]="COMMA",e[e.LPAREN=21]="LPAREN",e[e.RPAREN=22]="RPAREN",e[e.LBRACE=23]="LBRACE",e[e.RBRACE=24]="RBRACE",e[e.OPERATOR=25]="OPERATOR",e[e.AT=26]="AT",e[e.DOT=27]="DOT",e[e.INTERPOLATION_START=28]="INTERPOLATION_START",e[e.INTERPOLATION_END=29]="INTERPOLATION_END",e))(t||{}),o=(e=>(e[e.NUI_ROOT=0]="NUI_ROOT",e[e.IMPORT_DECLARATION=1]="IMPORT_DECLARATION",e[e.SIGNAL_DECLARATION=2]="SIGNAL_DECLARATION",e[e.FUNCTION_DECLARATION=3]="FUNCTION_DECLARATION",e[e.VIEW_BLOCK=4]="VIEW_BLOCK",e[e.STYLE_BLOCK=5]="STYLE_BLOCK",e))(o||{}),r=(e=>(e[e.UNEXPECTED_TOKEN=0]="UNEXPECTED_TOKEN",e[e.UNEXPECTED_EOF=1]="UNEXPECTED_EOF",e[e.INCONSISTENT_INDENT=2]="INCONSISTENT_INDENT",e[e.INVALID_STRING=3]="INVALID_STRING",e[e.INVALID_NUMBER=4]="INVALID_NUMBER",e[e.INVALID_IMPORT_SYNTAX=5]="INVALID_IMPORT_SYNTAX",e[e.INVALID_SIGNAL_SYNTAX=6]="INVALID_SIGNAL_SYNTAX",e[e.INVALID_FUNCTION_SYNTAX=7]="INVALID_FUNCTION_SYNTAX",e[e.INVALID_VIEW_SYNTAX=8]="INVALID_VIEW_SYNTAX",e[e.ELIF_WITHOUT_IF=9]="ELIF_WITHOUT_IF",e[e.ELSE_WITHOUT_IF=10]="ELSE_WITHOUT_IF",e[e.FOR_WITHOUT_IN=11]="FOR_WITHOUT_IN",e[e.UNTERMINATED_INTERPOLATION=12]="UNTERMINATED_INTERPOLATION",e[e.UNKNOWN_ERROR=13]="UNKNOWN_ERROR",e))(r||{});const s={import:7,from:8,function:9,if:10,elif:11,else:12,for:13,in:14,view:15,style:16,signal:17,asyncSignal:18},c="\n";function i(e,n,t){return{offset:e,line:n,column:t}}function l(e,n,t){return{start:e,end:n,source:t}}function u(e,n,t){const o=new SyntaxError(n);return o.code=e,o.loc=t,o}function f(e,n,t){return{type:e,value:n,loc:t}}function N(e){return{source:e,offset:0,line:1,column:1,indentStack:[0],tokens:[],errors:[]}}function E(e){return e.offset>=e.source.length?null:e.source[e.offset]}function I(e,n=1){const t=e.offset+n;return t>=e.source.length?null:e.source[t]}function a(e){const n=E(e);return null!==n&&(e.offset++,n===c?(e.line++,e.column=1):e.column++),n}function T(e){for(;" "===E(e);)a(e)}function p(e){let n=0;for(;"\t"===E(e);)n++,a(e);const t=E(e);return null===t||t===c?-1:n}function A(e,n,o){const s=[],c=e.indentStack[e.indentStack.length-1];if(n>c)e.indentStack.push(n),s.push(f(t.INDENT,"",o));else if(n<c){for(;e.indentStack.length>1&&e.indentStack[e.indentStack.length-1]>n;)e.indentStack.pop(),s.push(f(t.DEDENT,"",o));e.indentStack[e.indentStack.length-1]!==n&&e.errors.push(u(r.INCONSISTENT_INDENT,`缩进不一致:期望 ${e.indentStack[e.indentStack.length-1]} 个 Tab,但得到 ${n} 个`,o))}return s}function d(e){const n=l(i(e.offset,e.line,e.column),i(e.offset,e.line,e.column),""),o=a(e);let s="";for(;;){const t=E(e);if(null===t){e.errors.push(u(r.INVALID_STRING,"未终止的字符串",n));break}if(t===o){a(e);break}if("\\"===t){a(e);const n=E(e);if(null!==n)switch(a(e),n){case"n":s+="\n";break;case"t":s+="\t";break;case"r":s+="\r";break;case"\\":s+="\\";break;case'"':s+='"';break;case"'":s+="'";break;default:s+=n}}else s+=a(e)}const c=l(n.start,i(e.offset,e.line,e.column),"");return f(t.STRING,s,c)}function R(e){const n=e.offset,o=e.line,r=e.column;let s="",c=!1;for(;;){const n=E(e);if(null===n)break;if(n>="0"&&n<="9")s+=a(e);else{if("."!==n||c)break;{const n=I(e);if(!(null!==n&&n>="0"&&n<="9"))break;c=!0,s+=a(e)}}}const u=l(i(n,o,r),i(e.offset,e.line,e.column),"");return f(t.NUMBER,s,u)}function h(e){return/^[\p{L}]$/u.test(e)}function O(e){const n=e.offset,o=e.line,r=e.column;let c="";for(;;){const n=E(e);if(null===n)break;if(!(n>="a"&&n<="z"||n>="A"&&n<="Z"||n>="0"&&n<="9"||"_"===n||"$"===n||h(n)))break;c+=a(e)}const u=l(i(n,o,r),i(e.offset,e.line,e.column),""),N=s[c];return f(void 0!==N?N:t.IDENTIFIER,c,u)}function L(e){const n=N(e);let o=!0;for(;n.offset<e.length;){const e=E(n);if(o){if("\r"===e){a(n);continue}if(e===c){a(n);continue}const t=p(n);if(o=!1,-1===t){o=!0;continue}const r=A(n,t,l(i(n.offset,n.line,1),i(n.offset,n.line,1),""));n.tokens.push(...r);continue}if(e===c){const e=n.offset,r=n.line,s=n.column;a(n);const c=l(i(e,r,s),i(n.offset,n.line,n.column),"");n.tokens.push(f(t.NEWLINE,"\\n",c)),o=!0;continue}if("\r"===e){a(n);continue}if(" "===e){T(n);continue}if("/"===e&&"/"===I(n)){for(a(n),a(n);E(n)&&E(n)!==c;)a(n);continue}if("/"===e&&"*"===I(n)){for(a(n),a(n);E(n);){if("*"===E(n)&&"/"===I(n)){a(n),a(n);break}a(n)}continue}const s=n.offset,N=n.line,L=n.column;switch(e){case"\t":n.errors.push(u(r.INCONSISTENT_INDENT,"Tab 只能出现在行首",l(i(s,N,L),i(s+1,N,L+1),""))),a(n);break;case"@":a(n),n.tokens.push(f(t.AT,"@",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case"=":a(n),n.tokens.push(f(t.EQUALS,"=",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case",":a(n),n.tokens.push(f(t.COMMA,",",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case"(":a(n),n.tokens.push(f(t.LPAREN,"(",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case")":a(n),n.tokens.push(f(t.RPAREN,")",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case"{":a(n),n.tokens.push(f(t.LBRACE,"{",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case"}":a(n),n.tokens.push(f(t.RBRACE,"}",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case".":a(n),n.tokens.push(f(t.DOT,".",l(i(s,N,L),i(n.offset,N,L+1),"")));break;case"+":case"-":case"*":case"/":case"<":case">":case"!":case"&":case"|":case":":case";":case"?":case"%":a(n),n.tokens.push(f(t.OPERATOR,e,l(i(s,N,L),i(n.offset,N,L+1),"")));break;case'"':case"'":n.tokens.push(d(n));break;default:if(e>="0"&&e<="9"){n.tokens.push(R(n));break}if(e>="a"&&e<="z"||e>="A"&&e<="Z"||"_"===e||"$"===e||h(e)){n.tokens.push(O(n));break}n.errors.push(u(r.UNEXPECTED_TOKEN,`意外的字符: ${e}`,l(i(s,N,L),i(s+1,N,L+1),""))),a(n)}}const s=l(i(n.offset,n.line,n.column),i(n.offset,n.line,n.column),"");for(;n.indentStack.length>1;)n.indentStack.pop(),n.tokens.push(f(t.DEDENT,"",s));return n.tokens.push(f(t.EOF,"",s)),{tokens:n.tokens,errors:n.errors}}function S(e,n,t){return{start:e,end:n,source:t}}function D(e){return{tokens:e,index:0,currentToken:e[0]||null,errors:[],indentLevel:0}}function _(e){return e.currentToken}function y(e){return e.index++,e.currentToken=e.index<e.tokens.length?e.tokens[e.index]:null,e.currentToken}function k(e,n){return e.currentToken?.type===n}function m(e,n,t){if(k(e,n)){const n=e.currentToken;return y(e),n}return e.errors.push(function(e,n,t){const o=new SyntaxError(n);return o.code=e,o.loc=t,o}(r.UNEXPECTED_TOKEN,t,e.currentToken?.loc)),null}function g(e){for(;k(e,t.NEWLINE);)y(e)}function F(e){for(;k(e,t.INDENT)||k(e,t.DEDENT);)y(e)}function $(e){const n=_(e);if(!n)return null;const r=n.loc;if(!k(e,t.IMPORT))return null;y(e);const s=m(e,t.IDENTIFIER,"import 语句需要指定导入的标识符");if(!s)return null;const c=s.value;m(e,t.FROM,'import 语句需要 "from" 关键词');const i=m(e,t.STRING,"import 语句需要指定来源路径");if(!i)return null;return{type:o.IMPORT_DECLARATION,identifier:c,source:i.value,loc:S(r.start,i.loc.end,"")}}function C(e){const n=_(e);if(!n)return null;const r=n.loc;if(!k(e,t.IDENTIFIER))return null;const s=n.value;if(y(e),!k(e,t.EQUALS))return e.index--,e.currentToken=n,null;y(e);const c=k(e,t.ASYNC_SIGNAL);if(!c&&!k(e,t.SIGNAL))return e.index-=2,e.currentToken=e.tokens[e.index],null;y(e),m(e,t.LPAREN,"signal 声明需要括号");let i="";for(;_(e)&&!k(e,t.RPAREN);){const n=_(e);i+=n.type===t.STRING?`"${n.value}"`:n.value,y(e)}m(e,t.RPAREN,"signal 声明需要闭合括号");const l=_(e)?.loc||r;return{type:o.SIGNAL_DECLARATION,name:s,isAsync:c,initExpression:i,loc:S(r.start,l.end,"")}}function v(e){const n=_(e);if(!n)return null;const r=n.loc;if(!k(e,t.FUNCTION))return null;y(e);const s=m(e,t.IDENTIFIER,"函数声明需要指定函数名");if(!s)return null;const c=s.value,i=function(e){const n=[];if(!k(e,t.LPAREN))return n;for(y(e);!k(e,t.RPAREN);)if(k(e,t.IDENTIFIER)&&(n.push(_(e).value),y(e)),k(e,t.COMMA))y(e);else if(!k(e,t.RPAREN))break;return m(e,t.RPAREN,"函数参数列表需要闭合括号"),n}(e),l=function(e){if(!k(e,t.LBRACE))return"";y(e);let n="",o=1;for(;_(e)&&o>0;){const r=_(e);r.type===t.LBRACE?(o++,n+="{",y(e)):r.type===t.RBRACE?(o--,o>0&&(n+="}"),y(e)):r.type===t.NEWLINE?(n+="\n",y(e)):r.type===t.STRING?(n+=`"${r.value}"`,y(e)):(n+=r.value,y(e))}return n.trim()}(e),u=_(e)?.loc||r;return{type:o.FUNCTION_DECLARATION,name:c,params:i,body:l,loc:S(r.start,u.end,"")}}function b(e){const n=D(e),o=[],r=[],s=[];for(g(n);_(n)&&!k(n,t.EOF)&&(F(n),g(n),!k(n,t.EOF));){if(k(n,t.IMPORT)){const e=$(n);e&&o.push(e)}else if(k(n,t.FUNCTION)){const e=v(n);e&&s.push(e)}else if(k(n,t.IDENTIFIER)){const e=C(n);e?r.push(e):y(n)}else y(n);g(n)}return{imports:o,signals:r,functions:s,errors:n.errors}}function x(e){return!!/^[A-Z]/.test(e)||n.isNativeTag(e)}function U(e,n,t){const o=new SyntaxError(n);return o.code=e,o.loc=t,o}function P(e){let n="",o=0;for(;_(e)&&!k(e,t.NEWLINE);){const r=_(e);if(r.type===t.INDENT||r.type===t.DEDENT)break;if(r.type===t.LPAREN?o++:r.type===t.RPAREN&&o--,0===o&&r.type===t.COMMA)break;if(n+=r.type===t.STRING?`"${r.value}"`:r.value,y(e),0===o){const n=_(e);if(n){if(n.type===t.AT)break;if(n.type===t.IDENTIFIER){const o=e.index;if(y(e),k(e,t.EQUALS)){e.index=o,e.currentToken=n;break}e.index=o,e.currentToken=n}}}}return n.trim()}function W(n,o){const s=_(n);if(!s||s.type!==t.IDENTIFIER)return null;const c=s.value;if(!x(c))return null;y(n);const i=function(n){const o=[];for(;_(n)&&!k(n,t.NEWLINE);){const s=_(n);if(s.type===t.AT){const c=s;if(y(n),!k(n,t.IDENTIFIER)){n.errors.push(U(r.INVALID_VIEW_SYNTAX,"事件指令需要指定事件名",_(n)?.loc));break}const i=_(n).value;if(y(n),!k(n,t.EQUALS)){n.errors.push(U(r.INVALID_VIEW_SYNTAX,'事件指令需要 "="',_(n)?.loc));break}y(n);const l=P(n);if(!l){n.errors.push(U(r.INVALID_VIEW_SYNTAX,"事件指令需要指定处理函数",_(n)?.loc));break}o.push(e.createDirectiveNode("on",l,i,[],c.loc));continue}if(s.type===t.IDENTIFIER){const r=s.value;if(y(n),k(n,t.EQUALS)){y(n);const c=_(n),i=c?.type===t.STRING;let l="";const u=_(n);(u?.type===t.STRING||u?.type===t.IDENTIFIER||u?.type===t.NUMBER)&&(l=u.value,y(n));const f=e.createAttributeNode(r,l,s.loc);f.isStatic=i,o.push(f);continue}n.index--,n.currentToken=s;break}break}return o}(n);return e.createElementNode(c,i,[],s.loc)}function M(n,o){const s=_(n);if(!s||s.type!==t.IF)return null;const c=[];y(n);let i="";for(;_(n)&&!k(n,t.NEWLINE)&&!k(n,t.INDENT)&&!k(n,t.EOF);)i+=_(n).value,y(n);if(g(n),!k(n,t.INDENT))return n.errors.push(U(r.INVALID_VIEW_SYNTAX,"if 语句后需要缩进",_(n)?.loc)),null;y(n);const l=Y(n);for(c.push(e.createIfBranchNode(l,i?e.createSimpleExpression(i,!1):void 0,s.loc));k(n,t.ELIF);){y(n);let o="";for(;_(n)&&!k(n,t.NEWLINE)&&!k(n,t.INDENT)&&!k(n,t.EOF);)o+=_(n).value,y(n);if(g(n),!k(n,t.INDENT)){n.errors.push(U(r.INVALID_VIEW_SYNTAX,"elif 语句后需要缩进",_(n)?.loc));break}y(n);const s=Y(n);c.push(e.createIfBranchNode(s,o?e.createSimpleExpression(o,!1):void 0,_(n)?.loc))}if(k(n,t.ELSE))if(y(n),g(n),k(n,t.INDENT)){y(n);const t=Y(n);c.push(e.createIfBranchNode(t,void 0,_(n)?.loc))}else n.errors.push(U(r.INVALID_VIEW_SYNTAX,"else 语句后需要缩进",_(n)?.loc));return e.createIfNode(c,s.loc)}function V(n,o){const s=_(n);if(!s||s.type!==t.FOR)return null;if(y(n),!k(n,t.IDENTIFIER))return n.errors.push(U(r.INVALID_VIEW_SYNTAX,"for 语句需要指定迭代变量",_(n)?.loc)),null;const c=_(n).value;if(y(n),!k(n,t.IN))return n.errors.push(U(r.FOR_WITHOUT_IN,'for 语句需要 "in" 关键词',_(n)?.loc)),null;y(n);let i="";for(;_(n)&&!k(n,t.NEWLINE)&&!k(n,t.INDENT)&&!k(n,t.EOF);)i+=_(n).value,y(n);if(g(n),!k(n,t.INDENT))return n.errors.push(U(r.INVALID_VIEW_SYNTAX,"for 语句后需要缩进",_(n)?.loc)),null;y(n);const l=Y(n);return e.createForNode(e.createSimpleExpression(i,!1),c,l,void 0,void 0,s.loc)}function B(n){const o=[];let r="",s=null;const c=()=>{r&&(o.push(e.createTextNode(r,s)),r="",s=null)};for(;_(n)&&!k(n,t.EOF)&&!(k(n,t.NEWLINE)||k(n,t.INDENT)||k(n,t.DEDENT)||k(n,t.RBRACE));){const i=_(n);if(i.type===t.LBRACE){c(),y(n);let r="";for(;_(n)&&!k(n,t.RBRACE)&&!k(n,t.NEWLINE)&&!k(n,t.EOF);){r+=_(n).value,y(n)}k(n,t.RBRACE)&&y(n),r&&o.push(e.createInterpolationNode(e.createSimpleExpression(r,!1),i.loc));continue}i.type!==t.IDENTIFIER&&i.type!==t.STRING&&i.type!==t.NUMBER&&i.type!==t.COMMA&&i.type!==t.OPERATOR&&i.type!==t.DOT||(s||(s=i.loc),r+=i.value),y(n)}return c(),o}function Y(n,o){const s=[];for(;_(n)&&!k(n,t.EOF);){if(k(n,t.DEDENT)){y(n);break}if(k(n,t.NEWLINE)){y(n);continue}if(k(n,t.INDENT)){y(n);continue}const o=_(n);if(o.type===t.IF){const e=M(n);e&&s.push(e);continue}if(o.type!==t.ELIF&&o.type!==t.ELSE){if(o.type===t.FOR){const e=V(n);e&&s.push(e);continue}if(o.type!==t.IDENTIFIER){if(o.type===t.LBRACE){y(n);let r="";for(;_(n)&&!k(n,t.RBRACE)&&!k(n,t.NEWLINE)&&!k(n,t.EOF);){r+=_(n).value,y(n)}k(n,t.RBRACE)&&y(n),r&&s.push(e.createInterpolationNode(e.createSimpleExpression(r,!1),o.loc));continue}if(o.type===t.IDENTIFIER||o.type===t.NUMBER||o.type===t.STRING||o.type===t.COMMA||o.type===t.OPERATOR||o.type===t.DOT){let r="",c=o.loc;for(;_(n);){const e=_(n);if(e.type!==t.IDENTIFIER&&e.type!==t.NUMBER&&e.type!==t.STRING&&e.type!==t.COMMA&&e.type!==t.OPERATOR&&e.type!==t.DOT)break;r+=e.value,y(n)}r&&s.push(e.createTextNode(r,c));continue}y(n)}else if(x(o.value)){const o=W(n);if(o){const r=B(n);if(/^[A-Z]/.test(o.tag)&&0===o.props.length&&r.length>0){const n=[e.createTextNode(o.tag,o.loc),...r];s.push(...n);continue}if(r.length>0&&(o.children=r),g(n),k(n,t.INDENT)){y(n);const e=Y(n);e.length>0&&(o.children=o.children&&o.children.length>0?[...o.children,...e]:e)}s.push(o)}}else{const e=B(n);s.push(...e)}}else n.errors.push(U(o.type===t.ELIF?r.ELIF_WITHOUT_IF:r.ELSE_WITHOUT_IF,(o.type===t.ELIF?"elif":"else")+" 必须紧跟在 if 或 elif 之后",o.loc)),y(n)}return s}function G(e){const n=D(e);let s=!1;for(;_(n)&&!k(n,t.EOF);){if(k(n,t.VIEW)){s=!0,y(n);break}y(n)}if(!s)return{view:null,errors:[]};if(g(n),!k(n,t.INDENT))return n.errors.push(U(r.INVALID_VIEW_SYNTAX,"view 块后需要缩进",_(n)?.loc)),{view:null,errors:n.errors};y(n);const c=Y(n);return{view:{type:o.VIEW_BLOCK,children:c,loc:{start:{offset:0,line:1,column:1},end:{offset:0,line:1,column:1},source:""}},errors:n.errors}}function X(e,n){n.code+=`import ${e.identifier} from "${e.source}"\n`}function w(e,n){n.code+=`const ${e.name} = ${e.isAsync?"asyncSignal":"signal"}(${e.initExpression})\n`}function z(e,n){n.code+=`function ${e.name}(${e.params.join(", ")}) { ${e.body} }\n`}function K(t,o,r){const s=!n.isNativeTag(t.tag),c=[];if(c.push(s?t.tag:`"${t.tag}"`),t.props.length>0){const n=function(n){const t=[];for(const o of n.props)if(o.type===e.NodeTypes.ATTRIBUTE)if(o.value){const e=o.value.content;o.isStatic?t.push(`${o.name}: "${e}"`):/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?t.push(`${o.name}: ${e}`):t.push(`${o.name}: "${e}"`)}else t.push(`${o.name}: true`);else if(o.type===e.NodeTypes.DIRECTIVE&&"on"===o.name&&o.arg){const e=o.arg.content||o.arg,n=o.exp?o.exp.content:"undefined",r=`on${e.charAt(0).toUpperCase()}${e.slice(1)}`;t.push(`${r}: ${n}`)}if(0===t.length)return"null";return`{ ${t.join(", ")} }`}(t);c.push(n)}if(t.children.length>0){if(t.children.every(n=>n.type===e.NodeTypes.TEXT)){const e=t.children.map(e=>e.content).join(" ");c.push(`"${e}"`)}else if(1===t.children.length){const e=Z(t.children[0]);c.push(e)}else{const n=[];for(let o=0;o<t.children.length;o++){const r=t.children[o],s=Z(r);if(r.type===e.NodeTypes.TEXT&&o>0){}n.push(s)}c.push(`[${n.join(", ")}]`)}}return 1===c.length?`h(${c[0]})`:2===c.length?`h(${c[0]}, ${c[1]})`:`h(${c[0]}, ${c[1]}, ${c[2]})`}function Z(n,t,o){switch(n.type){case e.NodeTypes.ELEMENT:return K(n);case e.NodeTypes.TEXT:return function(e){if(!e.includes("{"))return`"${e}"`;const n=[];let t=0;const o=/\{([^}]+)\}/g;let r;for(;null!==(r=o.exec(e));){r.index>t&&n.push(`"${e.slice(t,r.index)}"`);const o=r[1].trim();/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(o)?n.push(`${o}()`):n.push(o),t=r.index+r[0].length}t<e.length&&n.push(`"${e.slice(t)}"`);if(1===n.length)return n[0];return`[${n.join(", ")}]`}(n.content);case e.NodeTypes.INTERPOLATION:const t=n.content.content||"";return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(t)?`${t}()`:t;case e.NodeTypes.IF:return function(e){const n=e.branches;if(0===n.length)return"null";let t="";for(let e=0;e<n.length;e++){const o=n[e];if(o.condition){const n=H(o.condition.content),r=j(o.children);0===e?t=`${n} ? ${r}`:t+=` : ${n} ? ${r}`}else{t+=` : ${j(o.children)}`}}return t}(n);case e.NodeTypes.FOR:return function(e){const n=e.source.content,t=e.valueAlias,o=e.children,r=j(o);return`${n}().map(${t} => ${r})`}(n);default:return"null"}}function H(e){let n=e;return n=n.replace(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b(?!\()/g,(e,n)=>["true","false","null","undefined","if","else","elif","for","in","view","style"].includes(n)?n:`${n}()`),n}function j(e,n,t){if(0===e.length)return"null";if(1===e.length)return Z(e[0]);return`[${e.map(e=>Z(e)).join(", ")}]`}function Q(n){const t={code:"",indentLevel:0};[...n.imports,...n.signals,...n.functions].map(()=>null).filter(Boolean);for(const e of n.imports)X(e,t);n.imports.length>0&&(t.code+="\n"),function(e,n,t,o){const r=new Set;e.length>0&&(r.add("signal"),e.some(e=>e.isAsync)&&r.add("asyncSignal")),t&&r.add("h"),r.size>0&&(o.code+=`import { ${Array.from(r).join(", ")} } from "@fluxion-ui/fluxion/runtime"\n`)}(n.signals,0,n.view,t),(n.signals.length>0||n.functions.length>0||n.view)&&(t.code+="\n");for(const e of n.signals)w(e,t);n.signals.length>0&&n.functions.length>0&&(t.code+="\n");for(const e of n.functions)z(e,t);n.functions.length>0&&n.view&&(t.code+="\n"),n.view&&function(e,n){if(n.code+="function render() {\n",n.code+="\treturn ",0===e.children.length)n.code+="null";else if(1===e.children.length)n.code+=Z(e.children[0]);else{const t=e.children.map(e=>Z(e)).join(",\n\t\t");n.code+=`[\n\t\t${t}\n\t]`}n.code+="\n}\n"}(n.view,t),n.style&&function(e,n){if(!e.content.trim())return;const t=`style_${Buffer.from(e.content).toString("base64").slice(0,8)}`;n.code+="\n// 注入样式\n",n.code+=";(function() {\n",n.code+="\tif (typeof document !== 'undefined') {\n",n.code+=`\t\tconst style = document.getElementById('${t}')\n`,n.code+="\t\tif (!style) {\n",n.code+="\t\t\tconst el = document.createElement('style')\n",n.code+=`\t\t\tel.id = '${t}'\n`,n.code+=`\t\t\tel.textContent = \`${e.content.replace(/`/g,"\\`").replace(/\$/g,"\\$")}\`\n`,n.code+="\t\t\tdocument.head.appendChild(el)\n",n.code+="\t\t}\n",n.code+="\t}\n",n.code+="})()\n"}(n.style,t),n.view&&(t.code+="\nexport default { render }\n");const o=n.view?e.createRoot(n.view.children):null;return{code:t.code,ast:n,templateAst:o,errors:[]}}function q(n,r={}){const{tokens:s,errors:c}=L(n);if(r.onError)for(const e of c)r.onError(e);const i=b(s),l=G(s),u=function(e,n){let r=null;for(const e of n)if(e.type===t.STYLE){r=e;break}if(!r)return{style:null,errors:[]};let s=r.loc.start.offset+5;for(;s<e.length&&"\n"!==e[s];)s++;s++,s<e.length&&"\t"===e[s]&&s++;let c="",i=s,l=!0;for(;i<e.length;){const n=e[i];"\n"===n?(c+=n,i++,l=!0):l&&"\t"===n?(i++,l=!1):(c+=n,i++,l=!1)}return{style:{type:o.STYLE_BLOCK,content:c.trim(),loc:r.loc},errors:[]}}(n,s);return{ast:{type:o.NUI_ROOT,imports:i.imports,signals:i.signals,functions:i.functions,view:l.view,style:u.style,loc:e.createSourceLocation({offset:0,line:1,column:1},{offset:n.length,line:1,column:1},n),source:n},errors:[...c,...i.errors,...l.errors,...u.errors]}}exports.KEYWORDS=s,exports.NuiErrorCodes=r,exports.NuiNodeTypes=o,exports.TokenType=t,exports.compile=function(e,n={}){const{ast:t,errors:o}=q(e,n),r=Q(t);return{...r,errors:[...o,...r.errors]}},exports.generateModule=Q,exports.initTokenizerState=N,exports.parse=q,exports.parseFunctionDeclaration=v,exports.parseImportDeclaration=$,exports.parseSignalDeclaration=C,exports.parseStatements=b,exports.parseViewBlock=G,exports.readUntilNewline=function(e){let n="";for(;;){const t=E(e);if(null===t||t===c)break;n+=a(e)}return n},exports.tokenize=L;
2
+ //# sourceMappingURL=compiler-nui.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-nui.cjs","sources":["../src/types.ts","../src/tokenizer.ts","../src/parser/statement.ts","../src/parser/template.ts","../src/codegen/index.ts","../src/index.ts"],"sourcesContent":["/**\n * compiler-nui 类型定义\n * 定义 NUI DSL 的 Token 类型、AST 节点类型等\n */\n\nimport {\n\tNodeTypes,\n\tSourceLocation,\n\tPosition,\n\tTemplateChildNode,\n\tRootNode\n} from '@fluxion-ui/compiler-core'\n\n// ==================== Token 类型 ====================\n\n/**\n * Token 类型枚举\n */\nexport const enum TokenType {\n\t// 结构\n\tINDENT, // 缩进增加\n\tDEDENT, // 缩进减少\n\tNEWLINE, // 换行\n\tEOF, // 结束\n\n\t// 字面量\n\tIDENTIFIER, // 标识符\n\tSTRING, // 字符串 \"...\"\n\tNUMBER, // 数字\n\n\t// 关键词\n\tIMPORT, // import\n\tFROM, // from\n\tFUNCTION, // function\n\tIF, // if\n\tELIF, // elif\n\tELSE, // else\n\tFOR, // for\n\tIN, // in\n\tVIEW, // view\n\tSTYLE, // style\n\tSIGNAL, // signal\n\tASYNC_SIGNAL, // asyncSignal\n\n\t// 操作符\n\tEQUALS, // =\n\tCOMMA, // ,\n\tLPAREN, // (\n\tRPAREN, // )\n\tLBRACE, // {\n\tRBRACE, // }\n\tOPERATOR, // + - * / < > ! & | 等\n\n\t// 特殊\n\tAT, // @ 事件符号\n\tDOT, // .\n\tINTERPOLATION_START, // { 插值开始(行内)\n\tINTERPOLATION_END // } 插值结束(行内)\n}\n\n/**\n * Token 接口\n */\nexport interface Token {\n\ttype: TokenType\n\tvalue: string\n\tloc: SourceLocation\n}\n\n// ==================== NUI AST 节点类型 ====================\n\n/**\n * NUI AST 节点类型枚举\n */\nexport const enum NuiNodeTypes {\n\tNUI_ROOT, // NUI 根节点\n\tIMPORT_DECLARATION, // import 声明\n\tSIGNAL_DECLARATION, // signal 声明\n\tFUNCTION_DECLARATION,// function 声明\n\tVIEW_BLOCK, // view 块\n\tSTYLE_BLOCK // style 块\n}\n\n// ==================== NUI 根节点 ====================\n\n/**\n * NUI 根节点\n */\nexport interface NuiRootNode {\n\ttype: NuiNodeTypes.NUI_ROOT\n\t// import 声明列表\n\timports: ImportDeclaration[]\n\t// signal 声明列表\n\tsignals: SignalDeclaration[]\n\t// function 声明列表\n\tfunctions: FunctionDeclaration[]\n\t// view 块(可选)\n\tview: ViewBlock | null\n\t// style 块(可选)\n\tstyle: StyleBlock | null\n\t// 源码位置\n\tloc: SourceLocation\n\t// 原始源码\n\tsource: string\n}\n\n// ==================== Import 声明 ====================\n\n/**\n * import 声明\n * import Title from \"./Title.nui\"\n */\nexport interface ImportDeclaration {\n\ttype: NuiNodeTypes.IMPORT_DECLARATION\n\t// 导入的标识符\n\tidentifier: string\n\t// 导入来源路径\n\tsource: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Signal 声明 ====================\n\n/**\n * signal 声明\n * count = signal(0)\n * users = asyncSignal(fetchUsers)\n */\nexport interface SignalDeclaration {\n\ttype: NuiNodeTypes.SIGNAL_DECLARATION\n\t// 变量名\n\tname: string\n\t// 是否为 asyncSignal\n\tisAsync: boolean\n\t// 初始值表达式\n\tinitExpression: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Function 声明 ====================\n\n/**\n * function 声明\n * function increment() { count.update(c => c + 1) }\n */\nexport interface FunctionDeclaration {\n\ttype: NuiNodeTypes.FUNCTION_DECLARATION\n\t// 函数名\n\tname: string\n\t// 参数列表\n\tparams: string[]\n\t// 函数体(原始代码字符串)\n\tbody: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== View 块 ====================\n\n/**\n * view 块\n * 包含模板子节点\n */\nexport interface ViewBlock {\n\ttype: NuiNodeTypes.VIEW_BLOCK\n\t// 模板子节点(复用 compiler-core 的类型)\n\tchildren: TemplateChildNode[]\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Style 块 ====================\n\n/**\n * style 块\n * 包含原始 CSS 代码\n */\nexport interface StyleBlock {\n\ttype: NuiNodeTypes.STYLE_BLOCK\n\t// CSS 内容\n\tcontent: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== 解析选项 ====================\n\n/**\n * NUI 解析选项\n */\nexport interface NuiParseOptions {\n\t// 文件名(用于错误提示)\n\tfilename?: string\n\t// 是否在浏览器环境\n\tisBrowser?: boolean\n\t// 错误回调\n\tonError?: (error: NuiCompilerError) => void\n}\n\n// ==================== 解析结果 ====================\n\n/**\n * NUI 解析结果\n */\nexport interface NuiParseResult {\n\t// 解析后的 AST\n\tast: NuiRootNode\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 编译结果 ====================\n\n/**\n * NUI 编译结果\n */\nexport interface NuiCompileResult {\n\t// 生成的代码\n\tcode: string\n\t// 解析后的 AST\n\tast: NuiRootNode\n\t// 模板 AST(compiler-core 格式)\n\ttemplateAst: RootNode | null\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 编译错误 ====================\n\n/**\n * NUI 编译错误\n */\nexport interface NuiCompilerError extends SyntaxError {\n\tcode: NuiErrorCodes\n\tloc?: SourceLocation\n}\n\n/**\n * NUI 错误代码\n */\nexport const enum NuiErrorCodes {\n\t// 词法错误\n\tUNEXPECTED_TOKEN,\n\tUNEXPECTED_EOF,\n\tINCONSISTENT_INDENT,\n\tINVALID_STRING,\n\tINVALID_NUMBER,\n\n\t// 语法错误\n\tINVALID_IMPORT_SYNTAX,\n\tINVALID_SIGNAL_SYNTAX,\n\tINVALID_FUNCTION_SYNTAX,\n\tINVALID_VIEW_SYNTAX,\n\tELIF_WITHOUT_IF,\n\tELSE_WITHOUT_IF,\n\tFOR_WITHOUT_IN,\n\tUNTERMINATED_INTERPOLATION,\n\n\t// 未知错误\n\tUNKNOWN_ERROR\n}\n\n// ==================== 词法分析器状态 ====================\n\n/**\n * 词法分析器状态\n */\nexport interface TokenizerState {\n\t// 源码\n\tsource: string\n\t// 当前位置\n\toffset: number\n\t// 当前行号\n\tline: number\n\t// 当前列号\n\tcolumn: number\n\t// 缩进栈\n\tindentStack: number[]\n\t// 当前 Token 列表\n\ttokens: Token[]\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 解析器状态 ====================\n\n/**\n * 解析器状态\n */\nexport interface ParserState {\n\t// Token 列表\n\ttokens: Token[]\n\t// 当前 Token 索引\n\tindex: number\n\t// 当前 Token\n\tcurrentToken: Token | null\n\t// 错误列表\n\terrors: NuiCompilerError[]\n\t// 当前缩进层级\n\tindentLevel: number\n}\n\n// ==================== 工具函数 ====================\n\n/**\n * 关键词映射表\n */\nexport const KEYWORDS: Record<string, TokenType> = {\n\timport: TokenType.IMPORT,\n\tfrom: TokenType.FROM,\n\tfunction: TokenType.FUNCTION,\n\tif: TokenType.IF,\n\telif: TokenType.ELIF,\n\telse: TokenType.ELSE,\n\tfor: TokenType.FOR,\n\tin: TokenType.IN,\n\tview: TokenType.VIEW,\n\tstyle: TokenType.STYLE,\n\tsignal: TokenType.SIGNAL,\n\tasyncSignal: TokenType.ASYNC_SIGNAL\n}","/**\n * NUI 词法分析器\n * 将源码分割为 Token 流,处理缩进敏感语法\n */\n\nimport {\n\tTokenType,\n\tToken,\n\tTokenizerState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tKEYWORDS\n} from './types'\nimport {\n\tSourceLocation,\n\tPosition\n} from '@fluxion-ui/compiler-core'\nimport { warn } from '@fluxion-ui/shared'\n\n// ==================== 常量 ====================\n\n/**\n * Tab 字符\n */\nconst TAB = '\\t'\n\n/**\n * 换行符\n */\nconst NEWLINE = '\\n'\n\n/**\n * 回车符\n */\nconst CARRIAGE_RETURN = '\\r'\n\n/**\n * 空格字符\n */\nconst SPACE = ' '\n\n// ==================== 工具函数 ====================\n\n/**\n * 创建位置对象\n */\nfunction createPosition(\n\toffset: number,\n\tline: number,\n\tcolumn: number\n): Position {\n\treturn { offset, line, column }\n}\n\n/**\n * 创建源码位置对象\n */\nfunction createSourceLocation(\n\tstart: Position,\n\tend: Position,\n\tsource: string\n): SourceLocation {\n\treturn { start, end, source }\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n/**\n * 创建 Token\n */\nfunction createToken(\n\ttype: TokenType,\n\tvalue: string,\n\tloc: SourceLocation\n): Token {\n\treturn { type, value, loc }\n}\n\n// ==================== 词法分析器 ====================\n\n/**\n * 初始化词法分析器状态\n */\nexport function initTokenizerState(source: string): TokenizerState {\n\treturn {\n\t\tsource,\n\t\toffset: 0,\n\t\tline: 1,\n\t\tcolumn: 1,\n\t\tindentStack: [0],\n\t\ttokens: [],\n\t\terrors: []\n\t}\n}\n\n/**\n * 获取当前字符\n */\nfunction currentChar(state: TokenizerState): string | null {\n\tif (state.offset >= state.source.length) {\n\t\treturn null\n\t}\n\treturn state.source[state.offset]\n}\n\n/**\n * 向前看 n 个字符\n */\nfunction peekChar(state: TokenizerState, n: number = 1): string | null {\n\tconst offset = state.offset + n\n\tif (offset >= state.source.length) {\n\t\treturn null\n\t}\n\treturn state.source[offset]\n}\n\n/**\n * 前进一个字符\n */\nfunction advance(state: TokenizerState): string | null {\n\tconst char = currentChar(state)\n\tif (char !== null) {\n\t\tstate.offset++\n\t\tif (char === NEWLINE) {\n\t\t\tstate.line++\n\t\t\tstate.column = 1\n\t\t} else {\n\t\t\tstate.column++\n\t\t}\n\t}\n\treturn char\n}\n\n/**\n * 跳过空白字符(不包含换行)\n */\nfunction skipWhitespace(state: TokenizerState): void {\n\twhile (currentChar(state) === SPACE) {\n\t\tadvance(state)\n\t}\n}\n\n/**\n * 计算当前行的缩进(Tab 数量)\n * 仅在行首调用\n */\nfunction countIndent(state: TokenizerState): number {\n\tlet indent = 0\n\tconst startOffset = state.offset\n\n\twhile (currentChar(state) === TAB) {\n\t\tindent++\n\t\tadvance(state)\n\t}\n\n\t// 如果这一行是空行或注释行,返回 -1 表示忽略\n\tconst char = currentChar(state)\n\tif (char === null || char === NEWLINE) {\n\t\treturn -1\n\t}\n\n\treturn indent\n}\n\n/**\n * 处理缩进变化\n * 返回需要生成的 INDENT/DEDENT Token 数量\n */\nfunction handleIndent(\n\tstate: TokenizerState,\n\tcurrentIndent: number,\n\tloc: SourceLocation\n): Token[] {\n\tconst tokens: Token[] = []\n\tconst topIndent = state.indentStack[state.indentStack.length - 1]\n\n\tif (currentIndent > topIndent) {\n\t\t// 缩进增加\n\t\tstate.indentStack.push(currentIndent)\n\t\ttokens.push(createToken(TokenType.INDENT, '', loc))\n\t} else if (currentIndent < topIndent) {\n\t\t// 缩进减少,可能需要多个 DEDENT\n\t\twhile (\n\t\t\tstate.indentStack.length > 1 &&\n\t\t\tstate.indentStack[state.indentStack.length - 1] > currentIndent\n\t\t) {\n\t\t\tstate.indentStack.pop()\n\t\t\ttokens.push(createToken(TokenType.DEDENT, '', loc))\n\t\t}\n\n\t\t// 检查缩进是否匹配\n\t\tif (state.indentStack[state.indentStack.length - 1] !== currentIndent) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INCONSISTENT_INDENT,\n\t\t\t\t`缩进不一致:期望 ${state.indentStack[state.indentStack.length - 1]} 个 Tab,但得到 ${currentIndent} 个`,\n\t\t\t\tloc\n\t\t\t))\n\t\t}\n\t}\n\n\treturn tokens\n}\n\n/**\n * 读取字符串字面量\n */\nfunction readString(state: TokenizerState): Token {\n\tconst startLoc = createSourceLocation(\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\tconst quote = advance(state) // 读取起始引号\n\tlet value = ''\n\tconst start = state.offset\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_STRING,\n\t\t\t\t'未终止的字符串',\n\t\t\t\tstartLoc\n\t\t\t))\n\t\t\tbreak\n\t\t}\n\n\t\tif (char === quote) {\n\t\t\tadvance(state) // 读取结束引号\n\t\t\tbreak\n\t\t}\n\n\t\tif (char === '\\\\') {\n\t\t\tadvance(state)\n\t\t\tconst escaped = currentChar(state)\n\t\t\tif (escaped !== null) {\n\t\t\t\tadvance(state)\n\t\t\t\t// 处理转义字符\n\t\t\t\tswitch (escaped) {\n\t\t\t\t\tcase 'n':\n\t\t\t\t\t\tvalue += '\\n'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 't':\n\t\t\t\t\t\tvalue += '\\t'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'r':\n\t\t\t\t\t\tvalue += '\\r'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase '\\\\':\n\t\t\t\t\t\tvalue += '\\\\'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase '\"':\n\t\t\t\t\t\tvalue += '\"'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tvalue += \"'\"\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue += escaped\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tvalue += advance(state)\n\t\t}\n\t}\n\n\tconst endLoc = createSourceLocation(\n\t\tstartLoc.start,\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\treturn createToken(TokenType.STRING, value, endLoc)\n}\n\n/**\n * 读取数字字面量\n */\nfunction readNumber(state: TokenizerState): Token {\n\tconst startOffset = state.offset\n\tconst startLine = state.line\n\tconst startColumn = state.column\n\n\tlet value = ''\n\tlet hasDecimal = false\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) break\n\n\t\tif (char >= '0' && char <= '9') {\n\t\t\tvalue += advance(state)\n\t\t} else if (char === '.' && !hasDecimal) {\n\t\t\tconst next = peekChar(state)\n\t\t\tif (next !== null && next >= '0' && next <= '9') {\n\t\t\t\thasDecimal = true\n\t\t\t\tvalue += advance(state)\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst loc = createSourceLocation(\n\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\treturn createToken(TokenType.NUMBER, value, loc)\n}\n\n/**\n * 检查字符是否是 Unicode 字母(包括中文)\n * Unicode 字母范围:\n * - \\u4E00-\\u9FFF: CJK 统一汉字\n * - \\u3400-\\u4DBF: CJK 扩展 A\n * - \\u20000-\\u2A6DF: CJK 扩展 B (需要代理对)\n * - \\u2A700-\\u2B73F: CJK 扩展 C\n * - \\u2B740-\\u2B81F: CJK 扩展 D\n * - \\u2B820-\\u2CEAF: CJK 扩展 E\n * - \\u3040-\\u30FF: 日文假名\n * - \\uAC00-\\uD7AF: 韩文\n * - 其他 Unicode 字母(通过 \\p{L} 匹配)\n */\nfunction isUnicodeLetter(char: string): boolean {\n\t// 使用正则表达式匹配 Unicode 字母\n\t// \\p{L} 匹配所有 Unicode 字母类别\n\treturn /^[\\p{L}]$/u.test(char)\n}\n\n/**\n * 读取标识符或关键词\n */\nfunction readIdentifier(state: TokenizerState): Token {\n\tconst startOffset = state.offset\n\tconst startLine = state.line\n\tconst startColumn = state.column\n\n\tlet value = ''\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) break\n\n\t\t// 标识符可以包含字母、数字、下划线、$、Unicode 字母(包括中文)\n\t\tif (\n\t\t\t(char >= 'a' && char <= 'z') ||\n\t\t\t(char >= 'A' && char <= 'Z') ||\n\t\t\t(char >= '0' && char <= '9') ||\n\t\t\tchar === '_' ||\n\t\t\tchar === '$' ||\n\t\t\tisUnicodeLetter(char)\n\t\t) {\n\t\t\tvalue += advance(state)\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst loc = createSourceLocation(\n\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\t// 检查是否为关键词\n\tconst keywordType = KEYWORDS[value]\n\tif (keywordType !== undefined) {\n\t\treturn createToken(keywordType, value, loc)\n\t}\n\n\treturn createToken(TokenType.IDENTIFIER, value, loc)\n}\n\n/**\n * 读取行内容直到换行\n * 用于处理函数体等内容\n */\nexport function readUntilNewline(state: TokenizerState): string {\n\tlet content = ''\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null || char === NEWLINE) {\n\t\t\tbreak\n\t\t}\n\t\tcontent += advance(state)\n\t}\n\treturn content\n}\n\n/**\n * 词法分析主函数\n */\nexport function tokenize(source: string): {\n\ttokens: Token[]\n\terrors: NuiCompilerError[]\n} {\n\tconst state = initTokenizerState(source)\n\tlet atLineStart = true\n\tlet pendingIndent = 0\n\n\twhile (state.offset < source.length) {\n\t\tconst char = currentChar(state)\n\n\t\t// 处理行首缩进\n\t\tif (atLineStart) {\n\t\t\t// 跳过回车符\n\t\t\tif (char === CARRIAGE_RETURN) {\n\t\t\t\tadvance(state)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 处理换行(空行)\n\t\t\tif (char === NEWLINE) {\n\t\t\t\tadvance(state)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 计算缩进\n\t\t\tconst indent = countIndent(state)\n\t\t\tatLineStart = false\n\n\t\t\t// 空行,继续\n\t\t\tif (indent === -1) {\n\t\t\t\tatLineStart = true\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 处理缩进变化\n\t\t\tconst loc = createSourceLocation(\n\t\t\t\tcreatePosition(state.offset, state.line, 1),\n\t\t\t\tcreatePosition(state.offset, state.line, 1),\n\t\t\t\t''\n\t\t\t)\n\t\t\tconst indentTokens = handleIndent(state, indent, loc)\n\t\t\tstate.tokens.push(...indentTokens)\n\n\t\t\t// 更新当前字符\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理换行\n\t\tif (char === NEWLINE) {\n\t\t\tconst startOffset = state.offset\n\t\t\tconst startLine = state.line\n\t\t\tconst startColumn = state.column\n\n\t\t\tadvance(state)\n\n\t\t\tconst loc = createSourceLocation(\n\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t\t\t''\n\t\t\t)\n\t\t\tstate.tokens.push(createToken(TokenType.NEWLINE, '\\\\n', loc))\n\t\t\tatLineStart = true\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过回车符\n\t\tif (char === CARRIAGE_RETURN) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过空格\n\t\tif (char === SPACE) {\n\t\t\tskipWhitespace(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理注释 // ...(跳过直到换行)\n\t\tif (char === '/' && peekChar(state) === '/') {\n\t\t\t// 跳过 //\n\t\t\tadvance(state)\n\t\t\tadvance(state)\n\t\t\t// 读取直到换行或文件结束\n\t\t\twhile (currentChar(state) && currentChar(state) !== NEWLINE) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理块注释 /* ... */\n\t\tif (char === '/' && peekChar(state) === '*') {\n\t\t\tadvance(state) // 跳过 /\n\t\t\tadvance(state) // 跳过 *\n\t\t\t// 读取直到 */\n\t\t\twhile (currentChar(state)) {\n\t\t\t\tif (currentChar(state) === '*' && peekChar(state) === '/') {\n\t\t\t\t\tadvance(state) // 跳过 *\n\t\t\t\t\tadvance(state) // 跳过 /\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 记录 Token 起始位置\n\t\tconst startOffset = state.offset\n\t\tconst startLine = state.line\n\t\tconst startColumn = state.column\n\n\t\t// 处理各种 Token\n\t\tswitch (char) {\n\t\t\tcase TAB:\n\t\t\t\t// Tab 只在行首有意义,其他位置视为错误\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INCONSISTENT_INDENT,\n\t\t\t\t\t'Tab 只能出现在行首',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(startOffset + 1, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tadvance(state)\n\t\t\t\tbreak\n\n\t\t\tcase '@':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.AT,\n\t\t\t\t\t'@',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '=':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.EQUALS,\n\t\t\t\t\t'=',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase ',':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.COMMA,\n\t\t\t\t\t',',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '(':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.LPAREN,\n\t\t\t\t\t'(',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase ')':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.RPAREN,\n\t\t\t\t\t')',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '{':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.LBRACE,\n\t\t\t\t\t'{',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '}':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.RBRACE,\n\t\t\t\t\t'}',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '.':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.DOT,\n\t\t\t\t\t'.',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\t// 操作符:+ - * / < > ! & | : ; ? %\n\t\t\tcase '+':\n\t\t\tcase '-':\n\t\t\tcase '*':\n\t\t\tcase '/':\n\t\t\tcase '<':\n\t\t\tcase '>':\n\t\t\tcase '!':\n\t\t\tcase '&':\n\t\t\tcase '|':\n\t\t\tcase ':':\n\t\t\tcase ';':\n\t\t\tcase '?':\n\t\t\tcase '%':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.OPERATOR,\n\t\t\t\t\tchar,\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '\"':\n\t\t\tcase \"'\":\n\t\t\t\tstate.tokens.push(readString(state))\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\t// 数字\n\t\t\t\tif (char >= '0' && char <= '9') {\n\t\t\t\t\tstate.tokens.push(readNumber(state))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t// 标识符或关键词(包括 Unicode 字母,如中文)\n\t\t\t\tif (\n\t\t\t\t\t(char >= 'a' && char <= 'z') ||\n\t\t\t\t\t(char >= 'A' && char <= 'Z') ||\n\t\t\t\t\tchar === '_' ||\n\t\t\t\t\tchar === '$' ||\n\t\t\t\t\tisUnicodeLetter(char)\n\t\t\t\t) {\n\t\t\t\t\tstate.tokens.push(readIdentifier(state))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t// 未知字符\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.UNEXPECTED_TOKEN,\n\t\t\t\t\t`意外的字符: ${char}`,\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(startOffset + 1, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tadvance(state)\n\t\t}\n\t}\n\n\t// 生成剩余的 DEDENT\n\tconst endLoc = createSourceLocation(\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\twhile (state.indentStack.length > 1) {\n\t\tstate.indentStack.pop()\n\t\tstate.tokens.push(createToken(TokenType.DEDENT, '', endLoc))\n\t}\n\n\t// 添加 EOF\n\tstate.tokens.push(createToken(TokenType.EOF, '', endLoc))\n\n\treturn {\n\t\ttokens: state.tokens,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 语句解析器\n * 解析 import、signal、function 声明\n */\n\nimport {\n\tToken,\n\tTokenType,\n\tParserState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tNuiNodeTypes\n} from '../types'\nimport {\n\tSourceLocation,\n\tPosition\n} from '@fluxion-ui/compiler-core'\n\n// ==================== 工具函数 ====================\n\n/**\n * 创建位置对象\n */\nfunction createPosition(\n\toffset: number,\n\tline: number,\n\tcolumn: number\n): Position {\n\treturn { offset, line, column }\n}\n\n/**\n * 创建源码位置对象\n */\nfunction createSourceLocation(\n\tstart: Position,\n\tend: Position,\n\tsource: string\n): SourceLocation {\n\treturn { start, end, source }\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n/**\n * 初始化解析器状态\n */\nexport function initParserState(tokens: Token[]): ParserState {\n\treturn {\n\t\ttokens,\n\t\tindex: 0,\n\t\tcurrentToken: tokens[0] || null,\n\t\terrors: [],\n\t\tindentLevel: 0\n\t}\n}\n\n/**\n * 获取当前 Token\n */\nexport function currentToken(state: ParserState): Token | null {\n\treturn state.currentToken\n}\n\n/**\n * 获取下一个 Token(不移动)\n */\nexport function peekToken(state: ParserState): Token | null {\n\tconst nextIndex = state.index + 1\n\tif (nextIndex >= state.tokens.length) {\n\t\treturn null\n\t}\n\treturn state.tokens[nextIndex]\n}\n\n/**\n * 前进到下一个 Token\n */\nexport function advance(state: ParserState): Token | null {\n\tstate.index++\n\tif (state.index < state.tokens.length) {\n\t\tstate.currentToken = state.tokens[state.index]\n\t} else {\n\t\tstate.currentToken = null\n\t}\n\treturn state.currentToken\n}\n\n/**\n * 检查当前 Token 是否为指定类型\n */\nexport function isTokenType(state: ParserState, type: TokenType): boolean {\n\treturn state.currentToken?.type === type\n}\n\n/**\n * 期望当前 Token 为指定类型,否则报错\n */\nexport function expectToken(\n\tstate: ParserState,\n\ttype: TokenType,\n\terrorMessage: string\n): Token | null {\n\tif (isTokenType(state, type)) {\n\t\tconst token = state.currentToken\n\t\tadvance(state)\n\t\treturn token\n\t}\n\n\tstate.errors.push(createError(\n\t\tNuiErrorCodes.UNEXPECTED_TOKEN,\n\t\terrorMessage,\n\t\tstate.currentToken?.loc\n\t))\n\treturn null\n}\n\n/**\n * 跳过换行 Token\n */\nexport function skipNewlines(state: ParserState): void {\n\twhile (isTokenType(state, TokenType.NEWLINE)) {\n\t\tadvance(state)\n\t}\n}\n\n/**\n * 跳过缩进/缩进 Token\n */\nexport function skipIndent(state: ParserState): void {\n\twhile (\n\t\tisTokenType(state, TokenType.INDENT) ||\n\t\tisTokenType(state, TokenType.DEDENT)\n\t) {\n\t\tadvance(state)\n\t}\n}\n\n// ==================== Import 解析 ====================\n\n/**\n * 解析 import 声明\n * import Title from \"./Title.nui\"\n */\nexport function parseImportDeclaration(state: ParserState): ImportDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望 'import'\n\tif (!isTokenType(state, TokenType.IMPORT)) {\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望标识符\n\tconst identifierToken = expectToken(\n\t\tstate,\n\t\tTokenType.IDENTIFIER,\n\t\t'import 语句需要指定导入的标识符'\n\t)\n\tif (!identifierToken) return null\n\n\tconst identifier = identifierToken.value\n\n\t// 期望 'from'\n\texpectToken(state, TokenType.FROM, 'import 语句需要 \"from\" 关键词')\n\n\t// 期望字符串\n\tconst sourceToken = expectToken(\n\t\tstate,\n\t\tTokenType.STRING,\n\t\t'import 语句需要指定来源路径'\n\t)\n\tif (!sourceToken) return null\n\n\tconst source = sourceToken.value\n\n\tconst endLoc = sourceToken.loc\n\n\treturn {\n\t\ttype: NuiNodeTypes.IMPORT_DECLARATION,\n\t\tidentifier,\n\t\tsource,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== Signal 解析 ====================\n\n/**\n * 解析 signal 声明\n * count = signal(0)\n * users = asyncSignal(fetchUsers)\n */\nexport function parseSignalDeclaration(state: ParserState): SignalDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望标识符\n\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\treturn null\n\t}\n\tconst name = startToken.value\n\tadvance(state)\n\n\t// 期望 '='\n\tif (!isTokenType(state, TokenType.EQUALS)) {\n\t\t// 不是 signal 声明,回退\n\t\tstate.index--\n\t\tstate.currentToken = startToken\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 检查是 signal 还是 asyncSignal\n\tconst isAsync = isTokenType(state, TokenType.ASYNC_SIGNAL)\n\tif (!isAsync && !isTokenType(state, TokenType.SIGNAL)) {\n\t\t// 不是 signal 声明,回退并返回 null\n\t\tstate.index -= 2 // 回退到标识符位置(跳过标识符和 =)\n\t\tstate.currentToken = state.tokens[state.index]\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望 '('\n\texpectToken(state, TokenType.LPAREN, 'signal 声明需要括号')\n\n\t// 读取初始化表达式(直到 ')')\n\tlet initExpression = ''\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.RPAREN)) {\n\t\tconst token = currentToken(state)!\n\t\t// 字符串字面量需要加引号\n\t\tif (token.type === TokenType.STRING) {\n\t\t\tinitExpression += `\"${token.value}\"`\n\t\t} else {\n\t\t\tinitExpression += token.value\n\t\t}\n\t\tadvance(state)\n\t}\n\n\t// 期望 ')'\n\texpectToken(state, TokenType.RPAREN, 'signal 声明需要闭合括号')\n\n\tconst endLoc = currentToken(state)?.loc || startLoc\n\n\treturn {\n\t\ttype: NuiNodeTypes.SIGNAL_DECLARATION,\n\t\tname,\n\t\tisAsync,\n\t\tinitExpression,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== Function 解析 ====================\n\n/**\n * 解析函数参数列表\n */\nfunction parseFunctionParams(state: ParserState): string[] {\n\tconst params: string[] = []\n\n\t// 期望 '('\n\tif (!isTokenType(state, TokenType.LPAREN)) {\n\t\treturn params\n\t}\n\tadvance(state)\n\n\t// 解析参数\n\twhile (!isTokenType(state, TokenType.RPAREN)) {\n\t\tif (isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\tparams.push(currentToken(state)!.value)\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过逗号\n\t\tif (isTokenType(state, TokenType.COMMA)) {\n\t\t\tadvance(state)\n\t\t} else if (!isTokenType(state, TokenType.RPAREN)) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// 期望 ')'\n\texpectToken(state, TokenType.RPAREN, '函数参数列表需要闭合括号')\n\n\treturn params\n}\n\n/**\n * 解析函数体\n * 函数体从 '{' 开始到 '}' 结束,需要处理嵌套的大括号\n */\nfunction parseFunctionBody(state: ParserState): string {\n\t// 期望 '{'\n\tif (!isTokenType(state, TokenType.LBRACE)) {\n\t\treturn ''\n\t}\n\tadvance(state)\n\n\tlet body = ''\n\tlet braceDepth = 1\n\n\twhile (currentToken(state) && braceDepth > 0) {\n\t\tconst token = currentToken(state)!\n\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\tbraceDepth++\n\t\t\tbody += '{'\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.RBRACE) {\n\t\t\tbraceDepth--\n\t\t\tif (braceDepth > 0) {\n\t\t\t\tbody += '}'\n\t\t\t}\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.NEWLINE) {\n\t\t\tbody += '\\n'\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.STRING) {\n\t\t\t// 字符串字面量需要加引号\n\t\t\tbody += `\"${token.value}\"`\n\t\t\tadvance(state)\n\t\t} else {\n\t\t\tbody += token.value\n\t\t\tadvance(state)\n\t\t}\n\t}\n\n\treturn body.trim()\n}\n\n/**\n * 解析 function 声明\n * function increment() { count.update(c => c + 1) }\n */\nexport function parseFunctionDeclaration(state: ParserState): FunctionDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望 'function'\n\tif (!isTokenType(state, TokenType.FUNCTION)) {\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望函数名\n\tconst nameToken = expectToken(\n\t\tstate,\n\t\tTokenType.IDENTIFIER,\n\t\t'函数声明需要指定函数名'\n\t)\n\tif (!nameToken) return null\n\n\tconst name = nameToken.value\n\n\t// 解析参数\n\tconst params = parseFunctionParams(state)\n\n\t// 解析函数体\n\tconst body = parseFunctionBody(state)\n\n\tconst endLoc = currentToken(state)?.loc || startLoc\n\n\treturn {\n\t\ttype: NuiNodeTypes.FUNCTION_DECLARATION,\n\t\tname,\n\t\tparams,\n\t\tbody,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== 语句解析入口 ====================\n\n/**\n * 语句解析结果\n */\nexport interface StatementParseResult {\n\timports: ImportDeclaration[]\n\tsignals: SignalDeclaration[]\n\tfunctions: FunctionDeclaration[]\n\terrors: NuiCompilerError[]\n}\n\n/**\n * 解析所有语句\n */\nexport function parseStatements(tokens: Token[]): StatementParseResult {\n\tconst state = initParserState(tokens)\n\n\tconst imports: ImportDeclaration[] = []\n\tconst signals: SignalDeclaration[] = []\n\tconst functions: FunctionDeclaration[] = []\n\n\t// 跳过开始的换行\n\tskipNewlines(state)\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 跳过缩进变化\n\t\tskipIndent(state)\n\t\tskipNewlines(state)\n\n\t\tif (isTokenType(state, TokenType.EOF)) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 尝试解析各种声明\n\t\tif (isTokenType(state, TokenType.IMPORT)) {\n\t\t\tconst decl = parseImportDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\timports.push(decl)\n\t\t\t}\n\t\t} else if (isTokenType(state, TokenType.FUNCTION)) {\n\t\t\tconst decl = parseFunctionDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\tfunctions.push(decl)\n\t\t\t}\n\t\t} else if (isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\t// 可能是 signal 声明\n\t\t\tconst decl = parseSignalDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\tsignals.push(decl)\n\t\t\t} else {\n\t\t\t\t// 无法识别的语句,跳过\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t} else {\n\t\t\t// 跳过无法识别的 Token\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过行尾\n\t\tskipNewlines(state)\n\t}\n\n\treturn {\n\t\timports,\n\t\tsignals,\n\t\tfunctions,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 模板解析器\n * 解析 view 块的缩进式语法\n */\n\nimport {\n\tToken,\n\tTokenType,\n\tParserState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tViewBlock,\n\tNuiNodeTypes\n} from '../types'\nimport {\n\tNodeTypes,\n\tElementTypes,\n\tSourceLocation,\n\tPosition,\n\tTemplateChildNode,\n\tElementNode,\n\tTextNode,\n\tInterpolationNode,\n\tIfNode,\n\tIfBranchNode,\n\tForNode,\n\tAttributeNode,\n\tDirectiveNode,\n\tSimpleExpressionNode\n} from '@fluxion-ui/compiler-core'\nimport {\n\tcreatePosition,\n\tcreateSourceLocation,\n\tcreateElementNode,\n\tcreateTextNode,\n\tcreateInterpolationNode,\n\tcreateAttributeNode,\n\tcreateDirectiveNode,\n\tcreateSimpleExpression,\n\tcreateIfNode,\n\tcreateIfBranchNode,\n\tcreateForNode\n} from '@fluxion-ui/compiler-core'\nimport { isNativeTag } from '@fluxion-ui/compiler-dom'\nimport {\n\tinitParserState,\n\tcurrentToken,\n\tadvance,\n\tisTokenType,\n\texpectToken,\n\tskipNewlines\n} from './statement'\n\n// ==================== 工具函数 ====================\n\n/**\n * 判断标识符是否是有效的元素标签\n * HTML 标签或组件(以大写字母开头)\n */\nfunction isValidElementTag(name: string): boolean {\n\t// 组件:以大写字母开头\n\tif (/^[A-Z]/.test(name)) {\n\t\treturn true\n\t}\n\t// HTML 标签\n\treturn isNativeTag(name)\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n// ==================== 属性解析 ====================\n\n/**\n * 读取完整的表达式(支持函数调用)\n * 例如:switchTab(\"counter\") 或 reset 或 counter + 1\n */\nfunction readExpression(state: ParserState): string {\n\tlet expr = ''\n\tlet parenDepth = 0 // 括号嵌套深度\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.NEWLINE)) {\n\t\tconst token = currentToken(state)!\n\n\t\t// 遇到 INDENT 或 DEDENT 停止\n\t\tif (token.type === TokenType.INDENT || token.type === TokenType.DEDENT) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 跟踪括号深度\n\t\tif (token.type === TokenType.LPAREN) {\n\t\t\tparenDepth++\n\t\t} else if (token.type === TokenType.RPAREN) {\n\t\t\tparenDepth--\n\t\t}\n\n\t\t// 如果括号深度为 0 且遇到逗号,可能是下一个属性的分隔符\n\t\tif (parenDepth === 0 && token.type === TokenType.COMMA) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 将 token 值添加到表达式\n\t\t// 字符串 token 需要加引号\n\t\tif (token.type === TokenType.STRING) {\n\t\t\t// 在函数参数中需要加引号\n\t\t\texpr += `\"${token.value}\"`\n\t\t} else {\n\t\t\texpr += token.value\n\t\t}\n\t\tadvance(state)\n\n\t\t// 如果括号深度归零且遇到某些 token,检查是否应该停止\n\t\tif (parenDepth === 0) {\n\t\t\t// 检查下一个 token,如果是属性开始符号(@ 或标识符后跟 =),停止\n\t\t\tconst next = currentToken(state)\n\t\t\tif (next) {\n\t\t\t\tif (next.type === TokenType.AT) {\n\t\t\t\t\t// 下一个是 @event 指令,停止\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif (next.type === TokenType.IDENTIFIER) {\n\t\t\t\t\t// 检查是否是 name=value 形式的属性\n\t\t\t\t\tconst savedIndex = state.index\n\t\t\t\t\tadvance(state)\n\t\t\t\t\tif (isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\t\t\t// 这是一个新属性,回退并停止\n\t\t\t\t\t\tstate.index = savedIndex\n\t\t\t\t\t\tstate.currentToken = next\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\t// 不是属性,继续,但需要恢复状态\n\t\t\t\t\tstate.index = savedIndex\n\t\t\t\t\tstate.currentToken = next\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn expr.trim()\n}\n\n/**\n * 解析元素属性\n * 支持:name=value, name=\"value\", @event=handler, @event=func(arg)\n */\nfunction parseElementProps(\n\tstate: ParserState\n): Array<AttributeNode | DirectiveNode> {\n\tconst props: Array<AttributeNode | DirectiveNode> = []\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.NEWLINE)) {\n\t\tconst token = currentToken(state)!\n\n\t\t// @event=handler 指令\n\t\tif (token.type === TokenType.AT) {\n\t\t\tconst atToken = token\n\t\t\tadvance(state) // 跳过 @\n\n\t\t\t// 读取事件名\n\t\t\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要指定事件名',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tconst eventName = currentToken(state)!.value\n\t\t\tadvance(state)\n\n\t\t\t// 期望 '='\n\t\t\tif (!isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要 \"=\"',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tadvance(state)\n\n\t\t\t// 读取完整的处理函数表达式(支持函数调用)\n\t\t\tconst handler = readExpression(state)\n\n\t\t\tif (!handler) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要指定处理函数',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// 创建指令节点\n\t\t\tprops.push(createDirectiveNode(\n\t\t\t\t'on', // 事件指令名\n\t\t\t\thandler,\n\t\t\t\teventName,\n\t\t\t\t[],\n\t\t\t\tatToken.loc\n\t\t\t))\n\t\t\tcontinue\n\t\t}\n\n\t\t// name=value 属性\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\tconst attrName = token.value\n\t\t\tadvance(state)\n\n\t\t\t// 检查是否有值\n\t\t\tif (isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\tadvance(state) // 跳过 '='\n\n\t\t\t\t// 检查第一个 token 是否是字符串\n\t\t\t\tconst firstToken = currentToken(state)\n\t\t\t\tconst isStaticValue = firstToken?.type === TokenType.STRING\n\n\t\t\t\t// 读取属性值(只读一个 token)\n\t\t\t\tlet attrValue = ''\n\t\t\t\tconst valueToken = currentToken(state)\n\n\t\t\t\tif (valueToken?.type === TokenType.STRING) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else if (valueToken?.type === TokenType.IDENTIFIER) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else if (valueToken?.type === TokenType.NUMBER) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t}\n\n\t\t\t\t// 创建属性节点,标记是否为静态值\n\t\t\t\tconst attr = createAttributeNode(\n\t\t\t\t\tattrName,\n\t\t\t\t\tattrValue,\n\t\t\t\t\ttoken.loc\n\t\t\t\t)\n\t\t\t\t// 使用自定义属性标记静态值\n\t\t\t\t;(attr as any).isStatic = isStaticValue\n\t\t\t\tprops.push(attr)\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\t// 没有 '=' 表示这不是属性,可能是文本内容\n\t\t\t\t// 回退并停止解析属性\n\t\t\t\tstate.index--\n\t\t\t\tstate.currentToken = token\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// 无法识别的 Token,跳过\n\t\tbreak\n\t}\n\n\treturn props\n}\n\n// ==================== 文本解析 ====================\n\n/**\n * 解析文本行\n * 可能包含纯文本或插值表达式\n * 例如:hello {name}! 或 Count: {count}\n */\nfunction parseTextLine(\n\tstate: ParserState\n): Array<TextNode | InterpolationNode> {\n\tconst nodes: Array<TextNode | InterpolationNode> = []\n\tlet textContent = ''\n\n\t// 记录起始位置\n\tconst startLoc = currentToken(state)?.loc\n\n\t// 读取直到换行或文件结束\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tconst token = currentToken(state)!\n\n\t\t// 标识符可能是文本的一部分\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 字符串\n\t\tif (token.type === TokenType.STRING) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 数字\n\t\tif (token.type === TokenType.NUMBER) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 其他 Token 视为文本的一部分或跳过\n\t\tbreak\n\t}\n\n\t// 处理文本内容中的插值\n\t// 这里简化处理:将整个文本作为一个文本节点\n\t// 后续在 codegen 阶段处理插值\n\tif (textContent) {\n\t\tnodes.push(createTextNode(textContent, startLoc || undefined))\n\t}\n\n\treturn nodes\n}\n\n// ==================== 元素解析 ====================\n\n/**\n * 解析元素\n * tag [props...]\n */\nfunction parseElement(\n\tstate: ParserState,\n\tindentLevel: number\n): ElementNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.IDENTIFIER) {\n\t\treturn null\n\t}\n\n\tconst tagName = startToken.value\n\n\t// 检查是否是有效的元素标签\n\t// 如果不是 HTML 标签也不是组件(大写开头),返回 null\n\tif (!isValidElementTag(tagName)) {\n\t\treturn null\n\t}\n\n\tadvance(state)\n\n\t// 解析属性\n\tconst props = parseElementProps(state)\n\n\t// 创建元素节点\n\tconst element = createElementNode(\n\t\ttagName,\n\t\tprops,\n\t\t[],\n\t\tstartToken.loc\n\t)\n\n\treturn element\n}\n\n// ==================== 控制流解析 ====================\n\n/**\n * 解析 if 语句\n * if condition\n * ...\n * elif condition\n * ...\n * else\n * ...\n */\nfunction parseIfStatement(\n\tstate: ParserState,\n\tindentLevel: number\n): IfNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.IF) {\n\t\treturn null\n\t}\n\n\tconst branches: IfBranchNode[] = []\n\n\t// 解析 if 分支\n\tadvance(state) // 跳过 if\n\n\t// 读取条件表达式\n\tlet condition = ''\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tcondition += currentToken(state)!.value\n\t\tadvance(state)\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望缩进\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'if 语句后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析 if 分支的子节点\n\tconst ifChildren = parseChildren(state, indentLevel + 1)\n\n\tbranches.push(createIfBranchNode(\n\t\tifChildren,\n\t\tcondition ? createSimpleExpression(condition, false) : undefined,\n\t\tstartToken.loc\n\t))\n\n\t// 解析 elif 分支\n\twhile (isTokenType(state, TokenType.ELIF)) {\n\t\tadvance(state) // 跳过 elif\n\n\t\t// 读取条件表达式\n\t\tlet elifCondition = ''\n\t\twhile (\n\t\t\tcurrentToken(state) &&\n\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t) {\n\t\t\telifCondition += currentToken(state)!.value\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过换行\n\t\tskipNewlines(state)\n\n\t\t// 期望缩进\n\t\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t'elif 语句后需要缩进',\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t\tbreak\n\t\t}\n\t\tadvance(state) // 跳过 INDENT\n\n\t\t// 解析 elif 分支的子节点\n\t\tconst elifChildren = parseChildren(state, indentLevel + 1)\n\n\t\tbranches.push(createIfBranchNode(\n\t\t\telifChildren,\n\t\t\telifCondition ? createSimpleExpression(elifCondition, false) : undefined,\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t}\n\n\t// 解析 else 分支\n\tif (isTokenType(state, TokenType.ELSE)) {\n\t\tadvance(state) // 跳过 else\n\n\t\t// 跳过换行\n\t\tskipNewlines(state)\n\n\t\t// 期望缩进\n\t\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t'else 语句后需要缩进',\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t} else {\n\t\t\tadvance(state) // 跳过 INDENT\n\n\t\t\t// 解析 else 分支的子节点\n\t\t\tconst elseChildren = parseChildren(state, indentLevel + 1)\n\n\t\t\tbranches.push(createIfBranchNode(\n\t\t\t\telseChildren,\n\t\t\t\tundefined, // else 无条件\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t}\n\t}\n\n\treturn createIfNode(branches, startToken.loc)\n}\n\n/**\n * 解析 for 语句\n * for item in list\n * ...\n */\nfunction parseForStatement(\n\tstate: ParserState,\n\tindentLevel: number\n): ForNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.FOR) {\n\t\treturn null\n\t}\n\n\tadvance(state) // 跳过 for\n\n\t// 读取迭代变量\n\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'for 语句需要指定迭代变量',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tconst valueAlias = currentToken(state)!.value\n\tadvance(state)\n\n\t// 期望 'in'\n\tif (!isTokenType(state, TokenType.IN)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.FOR_WITHOUT_IN,\n\t\t\t'for 语句需要 \"in\" 关键词',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 in\n\n\t// 读取源表达式\n\tlet source = ''\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tsource += currentToken(state)!.value\n\t\tadvance(state)\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望缩进\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'for 语句后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析子节点\n\tconst children = parseChildren(state, indentLevel + 1)\n\n\treturn createForNode(\n\t\tcreateSimpleExpression(source, false),\n\t\tvalueAlias,\n\t\tchildren,\n\t\tundefined, // keyAlias\n\t\tundefined, // indexAlias\n\t\tstartToken.loc\n\t)\n}\n\n// ==================== 子节点解析 ====================\n\n/**\n * 解析行内内容(元素后的文本和插值)\n * 例如:h1 {title} 或 p hello world\n */\nfunction parseInlineContent(state: ParserState): Array<TextNode | InterpolationNode> {\n\tconst nodes: Array<TextNode | InterpolationNode> = []\n\n\t// 收集连续的文本内容\n\tlet currentText = ''\n\tlet currentTextLoc: any = null\n\n\t// 辅助函数:将收集的文本推送到 nodes\n\tconst flushText = () => {\n\t\tif (currentText) {\n\t\t\tnodes.push(createTextNode(currentText, currentTextLoc))\n\t\t\tcurrentText = ''\n\t\t\tcurrentTextLoc = null\n\t\t}\n\t}\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 遇到换行、缩进、结束插值,停止\n\t\tif (\n\t\t\tisTokenType(state, TokenType.NEWLINE) ||\n\t\t\tisTokenType(state, TokenType.INDENT) ||\n\t\t\tisTokenType(state, TokenType.DEDENT) ||\n\t\t\tisTokenType(state, TokenType.RBRACE)\n\t\t) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst token = currentToken(state)!\n\n\t\t// 插值表达式 {expr}\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\t// 先刷新已收集的文本\n\t\t\tflushText()\n\n\t\t\tadvance(state) // 跳过 {\n\n\t\t\t// 读取插值内容\n\t\t\tlet expr = ''\n\t\t\twhile (\n\t\t\t\tcurrentToken(state) &&\n\t\t\t\t!isTokenType(state, TokenType.RBRACE) &&\n\t\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t\t) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\texpr += t.value\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 期望 }\n\t\t\tif (isTokenType(state, TokenType.RBRACE)) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 创建插值节点\n\t\t\tif (expr) {\n\t\t\t\tnodes.push(createInterpolationNode(\n\t\t\t\t\tcreateSimpleExpression(expr, false),\n\t\t\t\t\ttoken.loc\n\t\t\t\t))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 文本类 token:收集到 currentText\n\t\tif (\n\t\t\ttoken.type === TokenType.IDENTIFIER ||\n\t\t\ttoken.type === TokenType.STRING ||\n\t\t\ttoken.type === TokenType.NUMBER ||\n\t\t\ttoken.type === TokenType.COMMA ||\n\t\t\ttoken.type === TokenType.OPERATOR ||\n\t\t\ttoken.type === TokenType.DOT\n\t\t) {\n\t\t\t// 记录起始位置\n\t\t\tif (!currentTextLoc) {\n\t\t\t\tcurrentTextLoc = token.loc\n\t\t\t}\n\t\t\tcurrentText += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 其他 token 跳过\n\t\tadvance(state)\n\t}\n\n\t// 刷新剩余的文本\n\tflushText()\n\n\treturn nodes\n}\n\n/**\n * 解析子节点\n */\nfunction parseChildren(\n\tstate: ParserState,\n\tindentLevel: number\n): TemplateChildNode[] {\n\tconst children: TemplateChildNode[] = []\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 检查是否到达当前块的结束(DEDENT)\n\t\tif (isTokenType(state, TokenType.DEDENT)) {\n\t\t\tadvance(state) // 消耗 DEDENT\n\t\t\tbreak\n\t\t}\n\n\t\t// 跳过换行\n\t\tif (isTokenType(state, TokenType.NEWLINE)) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过额外的 INDENT\n\t\tif (isTokenType(state, TokenType.INDENT)) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\tconst token = currentToken(state)!\n\n\t\t// if 语句\n\t\tif (token.type === TokenType.IF) {\n\t\t\tconst ifNode = parseIfStatement(state, indentLevel)\n\t\t\tif (ifNode) {\n\t\t\t\tchildren.push(ifNode)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// elif/else 不应该单独出现\n\t\tif (token.type === TokenType.ELIF || token.type === TokenType.ELSE) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\ttoken.type === TokenType.ELIF\n\t\t\t\t\t? NuiErrorCodes.ELIF_WITHOUT_IF\n\t\t\t\t\t: NuiErrorCodes.ELSE_WITHOUT_IF,\n\t\t\t\t`${token.type === TokenType.ELIF ? 'elif' : 'else'} 必须紧跟在 if 或 elif 之后`,\n\t\t\t\ttoken.loc\n\t\t\t))\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// for 语句\n\t\tif (token.type === TokenType.FOR) {\n\t\t\tconst forNode = parseForStatement(state, indentLevel)\n\t\t\tif (forNode) {\n\t\t\t\tchildren.push(forNode)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 元素或文本\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\t// 检查是否是有效的元素标签\n\t\t\tif (isValidElementTag(token.value)) {\n\t\t\t\tconst element = parseElement(state, indentLevel)\n\t\t\t\tif (element) {\n\t\t\t\t\t// 先解析同一行的文本/插值内容\n\t\t\t\t\tconst inlineChildren = parseInlineContent(state)\n\n\t\t\t\t\t// 如果元素是组件(大写开头)、没有属性、且有行内文本内容\n\t\t\t\t\t// 则将整个行作为文本处理(用户想写的是文本,不是组件)\n\t\t\t\t\tif (/^[A-Z]/.test(element.tag) &&\n\t\t\t\t\t element.props.length === 0 &&\n\t\t\t\t\t inlineChildren.length > 0) {\n\t\t\t\t\t\t// 将标签名作为文本的一部分\n\t\t\t\t\t\tconst textNodes = [createTextNode(element.tag, element.loc), ...inlineChildren]\n\t\t\t\t\t\tchildren.push(...textNodes)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tif (inlineChildren.length > 0) {\n\t\t\t\t\t\telement.children = inlineChildren\n\t\t\t\t\t}\n\n\t\t\t\t\t// 检查是否有嵌套子节点(下一个 Token 是 INDENT)\n\t\t\t\t\tskipNewlines(state)\n\t\t\t\t\tif (isTokenType(state, TokenType.INDENT)) {\n\t\t\t\t\t\tadvance(state) // 消耗 INDENT\n\t\t\t\t\t\tconst elementChildren = parseChildren(state, indentLevel + 1)\n\t\t\t\t\t\t// 合并嵌套子节点\n\t\t\t\t\t\tif (elementChildren.length > 0) {\n\t\t\t\t\t\t\tif (element.children && element.children.length > 0) {\n\t\t\t\t\t\t\t\t// 如果已有行内内容,合并\n\t\t\t\t\t\t\t\telement.children = [...element.children, ...elementChildren]\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\telement.children = elementChildren\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchildren.push(element)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 不是有效的元素标签,作为文本处理\n\t\t\t\t// 收集同一行的所有文本内容\n\t\t\t\tconst textNodes = parseInlineContent(state)\n\t\t\t\tchildren.push(...textNodes)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 插值表达式 {expr} 作为独立的子节点\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\tadvance(state) // 跳过 {\n\n\t\t\t// 读取插值内容\n\t\t\tlet expr = ''\n\t\t\twhile (\n\t\t\t\tcurrentToken(state) &&\n\t\t\t\t!isTokenType(state, TokenType.RBRACE) &&\n\t\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t\t) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\texpr += t.value\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 期望 }\n\t\t\tif (isTokenType(state, TokenType.RBRACE)) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 创建插值节点\n\t\t\tif (expr) {\n\t\t\t\tchildren.push(createInterpolationNode(\n\t\t\t\t\tcreateSimpleExpression(expr, false),\n\t\t\t\t\ttoken.loc\n\t\t\t\t))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 文本类 token:收集连续的文本\n\t\tif (\n\t\t\ttoken.type === TokenType.IDENTIFIER ||\n\t\t\ttoken.type === TokenType.NUMBER ||\n\t\t\ttoken.type === TokenType.STRING ||\n\t\t\ttoken.type === TokenType.COMMA ||\n\t\t\ttoken.type === TokenType.OPERATOR ||\n\t\t\ttoken.type === TokenType.DOT\n\t\t) {\n\t\t\tlet textContent = ''\n\t\t\tlet textLoc: any = token.loc\n\n\t\t\t// 收集连续的文本 token\n\t\t\twhile (currentToken(state)) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\tif (\n\t\t\t\t\tt.type === TokenType.IDENTIFIER ||\n\t\t\t\t\tt.type === TokenType.NUMBER ||\n\t\t\t\t\tt.type === TokenType.STRING ||\n\t\t\t\t\tt.type === TokenType.COMMA ||\n\t\t\t\t\tt.type === TokenType.OPERATOR ||\n\t\t\t\t\tt.type === TokenType.DOT\n\t\t\t\t) {\n\t\t\t\t\ttextContent += t.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (textContent) {\n\t\t\t\tchildren.push(createTextNode(textContent, textLoc))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 无法识别的 Token,跳过\n\t\tadvance(state)\n\t}\n\n\treturn children\n}\n\n// ==================== View 块解析 ====================\n\n/**\n * 解析 view 块\n */\nexport function parseViewBlock(tokens: Token[]): {\n\tview: ViewBlock | null\n\terrors: NuiCompilerError[]\n} {\n\tconst state = initParserState(tokens)\n\n\t// 找到 view 关键词\n\tlet foundView = false\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\tif (isTokenType(state, TokenType.VIEW)) {\n\t\t\tfoundView = true\n\t\t\tadvance(state) // 跳过 view\n\t\t\tbreak\n\t\t}\n\t\tadvance(state)\n\t}\n\n\tif (!foundView) {\n\t\treturn {\n\t\t\tview: null,\n\t\t\terrors: []\n\t\t}\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望 INDENT\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'view 块后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn {\n\t\t\tview: null,\n\t\t\terrors: state.errors\n\t\t}\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析子节点\n\tconst children = parseChildren(state, 1)\n\n\tconst viewBlock: ViewBlock = {\n\t\ttype: NuiNodeTypes.VIEW_BLOCK,\n\t\tchildren,\n\t\tloc: {\n\t\t\tstart: { offset: 0, line: 1, column: 1 },\n\t\t\tend: { offset: 0, line: 1, column: 1 },\n\t\t\tsource: ''\n\t\t}\n\t}\n\n\treturn {\n\t\tview: viewBlock,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 模块代码生成器\n * 将 NUI AST 转换为 JavaScript 模块代码\n */\n\nimport {\n\tNuiRootNode,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tViewBlock,\n\tStyleBlock,\n\tNuiCompileResult\n} from '../types'\nimport {\n\tNodeTypes,\n\tElementNode,\n\tTextNode,\n\tInterpolationNode,\n\tIfNode,\n\tForNode,\n\tTemplateChildNode,\n\tRootNode,\n\tcreateRoot\n} from '@fluxion-ui/compiler-core'\nimport { isNativeTag } from '@fluxion-ui/compiler-dom'\nimport { warn } from '@fluxion-ui/shared'\n\n// ==================== 代码生成上下文 ====================\n\n/**\n * 代码生成上下文\n */\ninterface ModuleCodegenContext {\n\t// 生成的代码\n\tcode: string\n\t// 缩进级别\n\tindentLevel: number\n}\n\n/**\n * 创建代码生成上下文\n */\nfunction createModuleCodegenContext(): ModuleCodegenContext {\n\treturn {\n\t\tcode: '',\n\t\tindentLevel: 0\n\t}\n}\n\n// ==================== 缩进辅助 ====================\n\n/**\n * 获取缩进字符串\n */\nfunction indent(level: number): string {\n\treturn '\\t'.repeat(level)\n}\n\n// ==================== Import 代码生成 ====================\n\n/**\n * 生成用户 import 语句\n */\nfunction genImportDeclaration(\n\tdecl: ImportDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += `import ${decl.identifier} from \"${decl.source}\"\\n`\n}\n\n/**\n * 生成运行时 import 语句\n */\nfunction genRuntimeImports(\n\tsignals: SignalDeclaration[],\n\tfunctions: FunctionDeclaration[],\n\tview: ViewBlock | null,\n\tctx: ModuleCodegenContext\n): void {\n\tconst imports: Set<string> = new Set()\n\n\t// signal 相关\n\tif (signals.length > 0) {\n\t\timports.add('signal')\n\t\t// 检查是否有 asyncSignal\n\t\tif (signals.some(s => s.isAsync)) {\n\t\t\timports.add('asyncSignal')\n\t\t}\n\t}\n\n\t// render 相关\n\tif (view) {\n\t\timports.add('h')\n\t}\n\n\tif (imports.size > 0) {\n\t\tctx.code += `import { ${Array.from(imports).join(', ')} } from \"@fluxion-ui/fluxion/runtime\"\\n`\n\t}\n}\n\n// ==================== Signal 代码生成 ====================\n\n/**\n * 生成 signal 声明\n */\nfunction genSignalDeclaration(\n\tdecl: SignalDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tconst keyword = decl.isAsync ? 'asyncSignal' : 'signal'\n\tctx.code += `const ${decl.name} = ${keyword}(${decl.initExpression})\\n`\n}\n\n// ==================== Function 代码生成 ====================\n\n/**\n * 生成函数声明\n */\nfunction genFunctionDeclaration(\n\tdecl: FunctionDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += `function ${decl.name}(${decl.params.join(', ')}) { ${decl.body} }\\n`\n}\n\n// ==================== Render 函数代码生成 ====================\n\n/**\n * 生成元素节点代码\n */\nfunction genElementNode(\n\tnode: ElementNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst indentStr = indent(indentLevel)\n\tconst isComponent = !isNativeTag(node.tag)\n\n\t// 构建参数\n\tconst args: string[] = []\n\n\t// 第一个参数:标签名或组件\n\tif (isComponent) {\n\t\targs.push(node.tag) // 组件直接使用标识符\n\t} else {\n\t\targs.push(`\"${node.tag}\"`) // 原生标签使用字符串\n\t}\n\n\t// 第二个参数:props\n\tif (node.props.length > 0) {\n\t\tconst propsObj = genPropsObject(node)\n\t\targs.push(propsObj)\n\t}\n\n\t// 第三个参数:children\n\tif (node.children.length > 0) {\n\t\t// 检查是否所有子节点都是文本节点(没有插值)\n\t\tconst allText = node.children.every(\n\t\t\tchild => child.type === NodeTypes.TEXT\n\t\t)\n\n\t\tif (allText) {\n\t\t\t// 合并所有文本为一个字符串\n\t\t\tconst combinedText = (node.children as TextNode[])\n\t\t\t\t.map(child => child.content)\n\t\t\t\t.join(' ')\n\t\t\targs.push(`\"${combinedText}\"`)\n\t\t} else if (node.children.length === 1) {\n\t\t\tconst childCode = genChildNode(node.children[0], ctx, indentLevel)\n\t\t\targs.push(childCode)\n\t\t} else {\n\t\t\t// 混合内容:文本和插值\n\t\t\t// 需要处理文本节点之间的空格\n\t\t\tconst childrenParts: string[] = []\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i]\n\t\t\t\tconst childCode = genChildNode(child, ctx, indentLevel)\n\n\t\t\t\t// 如果当前是文本节点,且前一个也是文本节点,需要添加空格连接\n\t\t\t\tif (child.type === NodeTypes.TEXT && i > 0) {\n\t\t\t\t\tconst prevChild = node.children[i - 1]\n\t\t\t\t\tif (prevChild.type === NodeTypes.TEXT) {\n\t\t\t\t\t\t// 两个相邻的文本节点,用 + 连接并添加空格\n\t\t\t\t\t\t// 但由于我们分别处理,这里不需要额外处理\n\t\t\t\t\t\t// 因为每个文本节点已经用引号包裹\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tchildrenParts.push(childCode)\n\t\t\t}\n\t\t\targs.push(`[${childrenParts.join(', ')}]`)\n\t\t}\n\t}\n\n\t// 生成 h 调用\n\tif (args.length === 1) {\n\t\treturn `h(${args[0]})`\n\t} else if (args.length === 2) {\n\t\treturn `h(${args[0]}, ${args[1]})`\n\t} else {\n\t\treturn `h(${args[0]}, ${args[1]}, ${args[2]})`\n\t}\n}\n\n/**\n * 生成 props 对象代码\n */\nfunction genPropsObject(node: ElementNode): string {\n\tconst props: string[] = []\n\n\tfor (const prop of node.props) {\n\t\tif (prop.type === NodeTypes.ATTRIBUTE) {\n\t\t\t// 普通属性\n\t\t\tif (prop.value) {\n\t\t\t\tconst value = prop.value.content\n\t\t\t\t// 检查是否标记为静态值(字符串字面量)\n\t\t\t\tconst isStatic = (prop as any).isStatic\n\t\t\t\tif (isStatic) {\n\t\t\t\t\t// 静态字符串值,加引号\n\t\t\t\t\tprops.push(`${prop.name}: \"${value}\"`)\n\t\t\t\t} else if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(value)) {\n\t\t\t\t\t// 标识符(变量引用),直接使用\n\t\t\t\t\tprops.push(`${prop.name}: ${value}`)\n\t\t\t\t} else {\n\t\t\t\t\t// 其他情况,加引号\n\t\t\t\t\tprops.push(`${prop.name}: \"${value}\"`)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tprops.push(`${prop.name}: true`)\n\t\t\t}\n\t\t} else if (prop.type === NodeTypes.DIRECTIVE) {\n\t\t\t// 指令(主要是事件)\n\t\t\tif (prop.name === 'on' && prop.arg) {\n\t\t\t\tconst eventName = (prop.arg as any).content || prop.arg\n\t\t\t\tconst handler = prop.exp ? (prop.exp as any).content : 'undefined'\n\t\t\t\t// 转换事件名:click -> onClick\n\t\t\t\tconst handlerName = `on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`\n\t\t\t\tprops.push(`${handlerName}: ${handler}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (props.length === 0) {\n\t\treturn 'null'\n\t}\n\n\treturn `{ ${props.join(', ')} }`\n}\n\n/**\n * 生成子节点代码\n */\nfunction genChildNode(\n\tnode: TemplateChildNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tswitch (node.type) {\n\t\tcase NodeTypes.ELEMENT:\n\t\t\treturn genElementNode(node as ElementNode, ctx, indentLevel)\n\n\t\tcase NodeTypes.TEXT:\n\t\t\tconst textContent = (node as TextNode).content\n\t\t\t// 处理插值表达式 {xxx}\n\t\t\treturn genTextWithInterpolation(textContent)\n\n\t\tcase NodeTypes.INTERPOLATION:\n\t\t\tconst exp = (node as InterpolationNode).content\n\t\t\tconst exprContent = (exp as any).content || ''\n\t\t\t// 如果是简单标识符,添加 () 来调用 signal\n\t\t\tif (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(exprContent)) {\n\t\t\t\treturn `${exprContent}()`\n\t\t\t}\n\t\t\treturn exprContent\n\n\t\tcase NodeTypes.IF:\n\t\t\treturn genIfNode(node as IfNode, ctx, indentLevel)\n\n\t\tcase NodeTypes.FOR:\n\t\t\treturn genForNode(node as ForNode, ctx, indentLevel)\n\n\t\tdefault:\n\t\t\treturn 'null'\n\t}\n}\n\n/**\n * 处理包含插值表达式的文本\n * 例如:hello {name}! -> [\"hello \", name(), \"!\"]\n * 根据设计文档,{count} 被转换为 count() 来读取 signal 的值\n */\nfunction genTextWithInterpolation(text: string): string {\n\t// 检查是否包含插值\n\tif (!text.includes('{')) {\n\t\treturn `\"${text}\"`\n\t}\n\n\t// 解析插值表达式\n\tconst parts: string[] = []\n\tlet lastIndex = 0\n\tconst regex = /\\{([^}]+)\\}/g\n\tlet match\n\n\twhile ((match = regex.exec(text)) !== null) {\n\t\t// 添加前面的文本\n\t\tif (match.index > lastIndex) {\n\t\t\tparts.push(`\"${text.slice(lastIndex, match.index)}\"`)\n\t\t}\n\t\t// 添加插值表达式,转换为 signal 调用\n\t\t// 根据设计文档:{count} → count()\n\t\tconst expr = match[1].trim()\n\t\t// 如果是简单标识符,添加 () 调用\n\t\tif (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(expr)) {\n\t\t\tparts.push(`${expr}()`)\n\t\t} else {\n\t\t\t// 复杂表达式,保持原样(可能已经包含函数调用)\n\t\t\tparts.push(expr)\n\t\t}\n\t\tlastIndex = match.index + match[0].length\n\t}\n\n\t// 添加剩余的文本\n\tif (lastIndex < text.length) {\n\t\tparts.push(`\"${text.slice(lastIndex)}\"`)\n\t}\n\n\tif (parts.length === 1) {\n\t\treturn parts[0]\n\t}\n\n\treturn `[${parts.join(', ')}]`\n}\n\n/**\n * 将条件表达式中的 Signal 标识符转换为函数调用\n * 例如:loading -> loading()\n * 例如:status == \"loading\" -> status() == \"loading\"\n */\nfunction convertSignalAccess(condition: string): string {\n\t// 处理比较操作符周围的标识符\n\t// 匹配模式:标识符(不在引号内)后面跟着操作符\n\tconst operators = ['==', '!=', '===', '!==', '<', '>', '<=', '>=', '&&', '||']\n\n\tlet result = condition\n\n\t// 简单方法:将独立的标识符转换为函数调用\n\t// 匹配:单词边界开始的标识符,后面不是 ( (说明不是函数调用)\n\tresult = result.replace(/\\b([a-zA-Z_$][a-zA-Z0-9_$]*)\\b(?!\\()/g, (match, ident) => {\n\t\t// 排除关键字和字面量\n\t\tconst keywords = ['true', 'false', 'null', 'undefined', 'if', 'else', 'elif', 'for', 'in', 'view', 'style']\n\t\tif (keywords.includes(ident)) {\n\t\t\treturn ident\n\t\t}\n\t\treturn `${ident}()`\n\t})\n\n\treturn result\n}\n\n/**\n * 生成 if 节点代码\n */\nfunction genIfNode(\n\tnode: IfNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst branches = node.branches\n\n\tif (branches.length === 0) {\n\t\treturn 'null'\n\t}\n\n\t// 生成三元表达式链\n\tlet code = ''\n\n\tfor (let i = 0; i < branches.length; i++) {\n\t\tconst branch = branches[i]\n\n\t\tif (branch.condition) {\n\t\t\t// if 或 elif 分支\n\t\t\tconst rawCondition = (branch.condition as any).content\n\t\t\t// 将条件中的 Signal 标识符转换为函数调用\n\t\t\tconst condition = convertSignalAccess(rawCondition)\n\t\t\tconst consequent = genBranchChildren(branch.children, ctx, indentLevel)\n\n\t\t\tif (i === 0) {\n\t\t\t\t// 第一个分支\n\t\t\t\tcode = `${condition} ? ${consequent}`\n\t\t\t} else {\n\t\t\t\t// 后续分支\n\t\t\t\tcode += ` : ${condition} ? ${consequent}`\n\t\t\t}\n\t\t} else {\n\t\t\t// else 分支\n\t\t\tconst alternate = genBranchChildren(branch.children, ctx, indentLevel)\n\t\t\tcode += ` : ${alternate}`\n\t\t}\n\t}\n\n\treturn code\n}\n\n/**\n * 生成分支子节点代码\n */\nfunction genBranchChildren(\n\tchildren: TemplateChildNode[],\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tif (children.length === 0) {\n\t\treturn 'null'\n\t}\n\n\tif (children.length === 1) {\n\t\treturn genChildNode(children[0], ctx, indentLevel)\n\t}\n\n\tconst childrenCode = children\n\t\t.map(child => genChildNode(child, ctx, indentLevel))\n\t\t.join(', ')\n\treturn `[${childrenCode}]`\n}\n\n/**\n * 生成 for 节点代码\n */\nfunction genForNode(\n\tnode: ForNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst source = node.source.content\n\tconst valueAlias = node.valueAlias\n\tconst children = node.children\n\n\t// 生成 map 回调\n\tconst childrenCode = genBranchChildren(children, ctx, indentLevel + 1)\n\n\treturn `${source}().map(${valueAlias} => ${childrenCode})`\n}\n\n/**\n * 生成 render 函数\n */\nfunction genRenderFunction(\n\tview: ViewBlock,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += 'function render() {\\n'\n\tctx.code += '\\treturn '\n\n\tif (view.children.length === 0) {\n\t\tctx.code += 'null'\n\t} else if (view.children.length === 1) {\n\t\tctx.code += genChildNode(view.children[0], ctx, 1)\n\t} else {\n\t\tconst childrenCode = view.children\n\t\t\t.map(child => genChildNode(child, ctx, 1))\n\t\t\t.join(',\\n\\t\\t')\n\t\tctx.code += `[\\n\\t\\t${childrenCode}\\n\\t]`\n\t}\n\n\tctx.code += '\\n}\\n'\n}\n\n// ==================== Style 代码生成 ====================\n\n/**\n * 生成 style 块\n * 将 CSS 内容注入到文档中\n */\nfunction genStyleBlock(\n\tstyle: StyleBlock,\n\tctx: ModuleCodegenContext\n): void {\n\tif (!style.content.trim()) {\n\t\treturn\n\t}\n\n\t// 生成一个唯一的 style ID(基于内容 hash)\n\tconst styleId = `style_${Buffer.from(style.content).toString('base64').slice(0, 8)}`\n\n\t// 生成注入样式表的代码\n\tctx.code += `\\n// 注入样式\\n`\n\tctx.code += `;(function() {\\n`\n\tctx.code += `\\tif (typeof document !== 'undefined') {\\n`\n\tctx.code += `\\t\\tconst style = document.getElementById('${styleId}')\\n`\n\tctx.code += `\\t\\tif (!style) {\\n`\n\tctx.code += `\\t\\t\\tconst el = document.createElement('style')\\n`\n\tctx.code += `\\t\\t\\tel.id = '${styleId}'\\n`\n\tctx.code += `\\t\\t\\tel.textContent = \\`${style.content.replace(/`/g, '\\\\`').replace(/\\$/g, '\\\\$')}\\`\\n`\n\tctx.code += `\\t\\t\\tdocument.head.appendChild(el)\\n`\n\tctx.code += `\\t\\t}\\n`\n\tctx.code += `\\t}\\n`\n\tctx.code += `})()\\n`\n}\n\n// ==================== 主入口 ====================\n\n/**\n * 生成模块代码\n */\nexport function generateModule(\n\tast: NuiRootNode\n): NuiCompileResult {\n\tconst ctx = createModuleCodegenContext()\n\tconst errors = [...ast.imports, ...ast.signals, ...ast.functions]\n\t\t.map(() => null)\n\t\t.filter(Boolean) || []\n\n\t// 1. 生成用户 import 语句\n\tfor (const imp of ast.imports) {\n\t\tgenImportDeclaration(imp, ctx)\n\t}\n\n\t// 空行\n\tif (ast.imports.length > 0) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 2. 生成运行时 import 语句\n\tgenRuntimeImports(ast.signals, ast.functions, ast.view, ctx)\n\n\t// 空行\n\tif (ast.signals.length > 0 || ast.functions.length > 0 || ast.view) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 3. 生成 signal 声明\n\tfor (const signal of ast.signals) {\n\t\tgenSignalDeclaration(signal, ctx)\n\t}\n\n\t// 空行\n\tif (ast.signals.length > 0 && ast.functions.length > 0) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 4. 生成 function 定义\n\tfor (const fn of ast.functions) {\n\t\tgenFunctionDeclaration(fn, ctx)\n\t}\n\n\t// 空行\n\tif (ast.functions.length > 0 && ast.view) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 5. 生成 render 函数\n\tif (ast.view) {\n\t\tgenRenderFunction(ast.view, ctx)\n\t}\n\n\t// 6. 生成 style 块\n\tif (ast.style) {\n\t\tgenStyleBlock(ast.style, ctx)\n\t}\n\n\t// 7. 生成默认导出(组件对象)\n\tif (ast.view) {\n\t\tctx.code += '\\nexport default { render }\\n'\n\t}\n\n\t// 创建模板 AST(用于后续处理)\n\tconst templateAst: RootNode | null = ast.view\n\t\t? createRoot(ast.view.children)\n\t\t: null\n\n\treturn {\n\t\tcode: ctx.code,\n\t\tast,\n\t\ttemplateAst,\n\t\terrors: []\n\t}\n}","/**\n * compiler-nui\n * NUI DSL 编译器\n */\n\n// 导出枚举和值\nexport {\n\t// Token 类型\n\tTokenType,\n\n\t// NUI AST 节点类型\n\tNuiNodeTypes,\n\n\t// 错误代码\n\tNuiErrorCodes,\n\n\t// 工具\n\tKEYWORDS\n} from './types'\n\n// 导出类型(使用 type 关键字)\nexport type {\n\t// Token\n\tToken,\n\n\t// NUI AST 节点\n\tNuiRootNode,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tViewBlock,\n\tStyleBlock,\n\n\t// 解析选项\n\tNuiParseOptions,\n\tNuiParseResult,\n\tNuiCompileResult,\n\n\t// 错误\n\tNuiCompilerError,\n\n\t// 状态\n\tTokenizerState,\n\tParserState\n} from './types'\n\n// 导出词法分析器\nexport { tokenize, readUntilNewline, initTokenizerState } from './tokenizer'\n\n// 导出解析器\nexport {\n\tparseStatements,\n\tparseImportDeclaration,\n\tparseSignalDeclaration,\n\tparseFunctionDeclaration,\n\tparseViewBlock\n} from './parser'\n\n// 导出类型\nexport type { StatementParseResult } from './parser'\n\n// 导出代码生成器\nexport { generateModule } from './codegen'\n\n// ==================== 编译入口 ====================\n\nimport {\n\tNuiRootNode,\n\tNuiParseOptions,\n\tNuiParseResult,\n\tNuiCompileResult,\n\tNuiNodeTypes,\n\tViewBlock,\n\tStyleBlock,\n\tToken,\n\tTokenType,\n\tNuiCompilerError\n} from './types'\nimport { tokenize } from './tokenizer'\nimport { parseStatements, parseViewBlock } from './parser'\nimport { generateModule } from './codegen'\nimport { createSourceLocation, Position } from '@fluxion-ui/compiler-core'\n\n/**\n * 解析 NUI 源码为 AST\n */\nexport function parse(source: string, options: NuiParseOptions = {}): NuiParseResult {\n\t// 1. 词法分析\n\tconst { tokens, errors: tokenErrors } = tokenize(source)\n\n\tif (options.onError) {\n\t\tfor (const error of tokenErrors) {\n\t\t\toptions.onError(error)\n\t\t}\n\t}\n\n\t// 2. 解析语句\n\tconst statementResult = parseStatements(tokens)\n\n\t// 3. 解析 view 块\n\tconst viewResult = parseViewBlock(tokens)\n\n\t// 4. 解析 style 块\n\tconst styleResult = parseStyleBlock(source, tokens)\n\n\t// 5. 构建 AST\n\tconst ast: NuiRootNode = {\n\t\ttype: NuiNodeTypes.NUI_ROOT,\n\t\timports: statementResult.imports,\n\t\tsignals: statementResult.signals,\n\t\tfunctions: statementResult.functions,\n\t\tview: viewResult.view,\n\t\tstyle: styleResult.style,\n\t\tloc: createSourceLocation(\n\t\t\t{ offset: 0, line: 1, column: 1 } as Position,\n\t\t\t{ offset: source.length, line: 1, column: 1 } as Position,\n\t\t\tsource\n\t\t),\n\t\tsource\n\t}\n\n\t// 收集所有错误\n\tconst errors = [\n\t\t...tokenErrors,\n\t\t...statementResult.errors,\n\t\t...viewResult.errors,\n\t\t...styleResult.errors\n\t]\n\n\treturn { ast, errors }\n}\n\n/**\n * 解析 style 块\n * 从源码中提取 style 块的内容\n */\nfunction parseStyleBlock(source: string, tokens: Token[]): {\n\tstyle: StyleBlock | null\n\terrors: NuiCompilerError[]\n} {\n\t// 找到 STYLE token\n\tlet styleToken: Token | null = null\n\tfor (const token of tokens) {\n\t\tif (token.type === TokenType.STYLE) {\n\t\t\tstyleToken = token\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (!styleToken) {\n\t\treturn { style: null, errors: [] }\n\t}\n\n\t// 从 style 关键字后面开始,找到缩进后的内容\n\t// style 关键字的位置\n\tconst styleStart = styleToken.loc.start.offset\n\n\t// 找到 style 后的换行符\n\tlet contentStart = styleStart + 5 // 'style'.length\n\twhile (contentStart < source.length && source[contentStart] !== '\\n') {\n\t\tcontentStart++\n\t}\n\tcontentStart++ // 跳过换行\n\n\t// 跳过缩进(第一个 tab)\n\tif (contentStart < source.length && source[contentStart] === '\\t') {\n\t\tcontentStart++\n\t}\n\n\t// 提取 style 内容直到文件末尾\n\t// 需要处理缩进:移除每行开头的 tab\n\tlet content = ''\n\tlet i = contentStart\n\tlet lineStart = true\n\n\twhile (i < source.length) {\n\t\tconst char = source[i]\n\n\t\tif (char === '\\n') {\n\t\t\tcontent += char\n\t\t\ti++\n\t\t\tlineStart = true\n\t\t} else if (lineStart && char === '\\t') {\n\t\t\t// 跳过行首的 tab(缩进)\n\t\t\ti++\n\t\t\tlineStart = false\n\t\t} else {\n\t\t\tcontent += char\n\t\t\ti++\n\t\t\tlineStart = false\n\t\t}\n\t}\n\n\t// 创建 style 块\n\tconst styleBlock: StyleBlock = {\n\t\ttype: NuiNodeTypes.STYLE_BLOCK,\n\t\tcontent: content.trim(),\n\t\tloc: styleToken.loc\n\t}\n\n\treturn { style: styleBlock, errors: [] }\n}\n\n/**\n * 编译 NUI 源码为 JavaScript 代码\n */\nexport function compile(source: string, options: NuiParseOptions = {}): NuiCompileResult {\n\t// 解析\n\tconst { ast, errors } = parse(source, options)\n\n\t// 代码生成\n\tconst result = generateModule(ast)\n\n\treturn {\n\t\t...result,\n\t\terrors: [...errors, ...result.errors]\n\t}\n}"],"names":["TokenType","NuiNodeTypes","NuiErrorCodes","KEYWORDS","import","from","function","if","elif","else","for","in","view","style","signal","asyncSignal","NEWLINE","createPosition","offset","line","column","createSourceLocation","start","end","source","createError","code","message","loc","error","SyntaxError","createToken","type","value","initTokenizerState","indentStack","tokens","errors","currentChar","state","length","peekChar","n","advance","char","skipWhitespace","countIndent","indent","handleIndent","currentIndent","topIndent","push","INDENT","pop","DEDENT","INCONSISTENT_INDENT","readString","startLoc","quote","INVALID_STRING","escaped","endLoc","STRING","readNumber","startOffset","startLine","startColumn","hasDecimal","next","NUMBER","isUnicodeLetter","test","readIdentifier","keywordType","IDENTIFIER","tokenize","atLineStart","indentTokens","AT","EQUALS","COMMA","LPAREN","RPAREN","LBRACE","RBRACE","DOT","OPERATOR","UNEXPECTED_TOKEN","EOF","initParserState","index","currentToken","indentLevel","isTokenType","expectToken","errorMessage","token","skipNewlines","skipIndent","parseImportDeclaration","startToken","IMPORT","identifierToken","identifier","FROM","sourceToken","IMPORT_DECLARATION","parseSignalDeclaration","name","isAsync","ASYNC_SIGNAL","SIGNAL","initExpression","SIGNAL_DECLARATION","parseFunctionDeclaration","FUNCTION","nameToken","params","parseFunctionParams","body","braceDepth","trim","parseFunctionBody","FUNCTION_DECLARATION","parseStatements","imports","signals","functions","decl","isValidElementTag","isNativeTag","readExpression","expr","parenDepth","savedIndex","parseElement","tagName","props","atToken","INVALID_VIEW_SYNTAX","eventName","handler","createDirectiveNode","attrName","firstToken","isStaticValue","attrValue","valueToken","attr","createAttributeNode","isStatic","parseElementProps","createElementNode","parseIfStatement","IF","branches","condition","ifChildren","parseChildren","createIfBranchNode","createSimpleExpression","ELIF","elifCondition","elifChildren","ELSE","elseChildren","createIfNode","parseForStatement","FOR","valueAlias","IN","FOR_WITHOUT_IN","children","createForNode","parseInlineContent","nodes","currentText","currentTextLoc","flushText","createTextNode","createInterpolationNode","ifNode","forNode","textContent","textLoc","t","element","inlineChildren","tag","textNodes","elementChildren","ELIF_WITHOUT_IF","ELSE_WITHOUT_IF","parseViewBlock","foundView","VIEW","VIEW_BLOCK","genImportDeclaration","ctx","genSignalDeclaration","genFunctionDeclaration","join","genElementNode","node","isComponent","args","propsObj","prop","NodeTypes","ATTRIBUTE","content","DIRECTIVE","arg","exp","handlerName","charAt","toUpperCase","slice","genPropsObject","every","child","TEXT","combinedText","map","childCode","genChildNode","childrenParts","i","ELEMENT","text","includes","parts","lastIndex","regex","match","exec","genTextWithInterpolation","INTERPOLATION","exprContent","branch","convertSignalAccess","consequent","genBranchChildren","genIfNode","childrenCode","genForNode","result","replace","ident","generateModule","ast","filter","Boolean","imp","Set","add","some","s","size","Array","genRuntimeImports","fn","genRenderFunction","styleId","Buffer","toString","genStyleBlock","templateAst","createRoot","parse","options","tokenErrors","onError","statementResult","viewResult","styleResult","styleToken","STYLE","contentStart","lineStart","STYLE_BLOCK","parseStyleBlock","NUI_ROOT"],"mappings":"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"}
@@ -0,0 +1,299 @@
1
+ import { SourceLocation, TemplateChildNode, RootNode } from '@fluxion-ui/compiler-core';
2
+
3
+ /**
4
+ * compiler-nui 类型定义
5
+ * 定义 NUI DSL 的 Token 类型、AST 节点类型等
6
+ */
7
+
8
+ /**
9
+ * Token 类型枚举
10
+ */
11
+ declare const enum TokenType {
12
+ INDENT = 0,// 缩进增加
13
+ DEDENT = 1,// 缩进减少
14
+ NEWLINE = 2,// 换行
15
+ EOF = 3,// 结束
16
+ IDENTIFIER = 4,// 标识符
17
+ STRING = 5,// 字符串 "..."
18
+ NUMBER = 6,// 数字
19
+ IMPORT = 7,// import
20
+ FROM = 8,// from
21
+ FUNCTION = 9,// function
22
+ IF = 10,// if
23
+ ELIF = 11,// elif
24
+ ELSE = 12,// else
25
+ FOR = 13,// for
26
+ IN = 14,// in
27
+ VIEW = 15,// view
28
+ STYLE = 16,// style
29
+ SIGNAL = 17,// signal
30
+ ASYNC_SIGNAL = 18,// asyncSignal
31
+ EQUALS = 19,// =
32
+ COMMA = 20,// ,
33
+ LPAREN = 21,// (
34
+ RPAREN = 22,// )
35
+ LBRACE = 23,// {
36
+ RBRACE = 24,// }
37
+ OPERATOR = 25,// + - * / < > ! & | 等
38
+ AT = 26,// @ 事件符号
39
+ DOT = 27,// .
40
+ INTERPOLATION_START = 28,// { 插值开始(行内)
41
+ INTERPOLATION_END = 29
42
+ }
43
+ /**
44
+ * Token 接口
45
+ */
46
+ interface Token {
47
+ type: TokenType;
48
+ value: string;
49
+ loc: SourceLocation;
50
+ }
51
+ /**
52
+ * NUI AST 节点类型枚举
53
+ */
54
+ declare const enum NuiNodeTypes {
55
+ NUI_ROOT = 0,// NUI 根节点
56
+ IMPORT_DECLARATION = 1,// import 声明
57
+ SIGNAL_DECLARATION = 2,// signal 声明
58
+ FUNCTION_DECLARATION = 3,// function 声明
59
+ VIEW_BLOCK = 4,// view 块
60
+ STYLE_BLOCK = 5
61
+ }
62
+ /**
63
+ * NUI 根节点
64
+ */
65
+ interface NuiRootNode {
66
+ type: NuiNodeTypes.NUI_ROOT;
67
+ imports: ImportDeclaration[];
68
+ signals: SignalDeclaration[];
69
+ functions: FunctionDeclaration[];
70
+ view: ViewBlock | null;
71
+ style: StyleBlock | null;
72
+ loc: SourceLocation;
73
+ source: string;
74
+ }
75
+ /**
76
+ * import 声明
77
+ * import Title from "./Title.nui"
78
+ */
79
+ interface ImportDeclaration {
80
+ type: NuiNodeTypes.IMPORT_DECLARATION;
81
+ identifier: string;
82
+ source: string;
83
+ loc: SourceLocation;
84
+ }
85
+ /**
86
+ * signal 声明
87
+ * count = signal(0)
88
+ * users = asyncSignal(fetchUsers)
89
+ */
90
+ interface SignalDeclaration {
91
+ type: NuiNodeTypes.SIGNAL_DECLARATION;
92
+ name: string;
93
+ isAsync: boolean;
94
+ initExpression: string;
95
+ loc: SourceLocation;
96
+ }
97
+ /**
98
+ * function 声明
99
+ * function increment() { count.update(c => c + 1) }
100
+ */
101
+ interface FunctionDeclaration {
102
+ type: NuiNodeTypes.FUNCTION_DECLARATION;
103
+ name: string;
104
+ params: string[];
105
+ body: string;
106
+ loc: SourceLocation;
107
+ }
108
+ /**
109
+ * view 块
110
+ * 包含模板子节点
111
+ */
112
+ interface ViewBlock {
113
+ type: NuiNodeTypes.VIEW_BLOCK;
114
+ children: TemplateChildNode[];
115
+ loc: SourceLocation;
116
+ }
117
+ /**
118
+ * style 块
119
+ * 包含原始 CSS 代码
120
+ */
121
+ interface StyleBlock {
122
+ type: NuiNodeTypes.STYLE_BLOCK;
123
+ content: string;
124
+ loc: SourceLocation;
125
+ }
126
+ /**
127
+ * NUI 解析选项
128
+ */
129
+ interface NuiParseOptions {
130
+ filename?: string;
131
+ isBrowser?: boolean;
132
+ onError?: (error: NuiCompilerError) => void;
133
+ }
134
+ /**
135
+ * NUI 解析结果
136
+ */
137
+ interface NuiParseResult {
138
+ ast: NuiRootNode;
139
+ errors: NuiCompilerError[];
140
+ }
141
+ /**
142
+ * NUI 编译结果
143
+ */
144
+ interface NuiCompileResult {
145
+ code: string;
146
+ ast: NuiRootNode;
147
+ templateAst: RootNode | null;
148
+ errors: NuiCompilerError[];
149
+ }
150
+ /**
151
+ * NUI 编译错误
152
+ */
153
+ interface NuiCompilerError extends SyntaxError {
154
+ code: NuiErrorCodes;
155
+ loc?: SourceLocation;
156
+ }
157
+ /**
158
+ * NUI 错误代码
159
+ */
160
+ declare const enum NuiErrorCodes {
161
+ UNEXPECTED_TOKEN = 0,
162
+ UNEXPECTED_EOF = 1,
163
+ INCONSISTENT_INDENT = 2,
164
+ INVALID_STRING = 3,
165
+ INVALID_NUMBER = 4,
166
+ INVALID_IMPORT_SYNTAX = 5,
167
+ INVALID_SIGNAL_SYNTAX = 6,
168
+ INVALID_FUNCTION_SYNTAX = 7,
169
+ INVALID_VIEW_SYNTAX = 8,
170
+ ELIF_WITHOUT_IF = 9,
171
+ ELSE_WITHOUT_IF = 10,
172
+ FOR_WITHOUT_IN = 11,
173
+ UNTERMINATED_INTERPOLATION = 12,
174
+ UNKNOWN_ERROR = 13
175
+ }
176
+ /**
177
+ * 词法分析器状态
178
+ */
179
+ interface TokenizerState {
180
+ source: string;
181
+ offset: number;
182
+ line: number;
183
+ column: number;
184
+ indentStack: number[];
185
+ tokens: Token[];
186
+ errors: NuiCompilerError[];
187
+ }
188
+ /**
189
+ * 解析器状态
190
+ */
191
+ interface ParserState {
192
+ tokens: Token[];
193
+ index: number;
194
+ currentToken: Token | null;
195
+ errors: NuiCompilerError[];
196
+ indentLevel: number;
197
+ }
198
+ /**
199
+ * 关键词映射表
200
+ */
201
+ declare const KEYWORDS: Record<string, TokenType>;
202
+
203
+ /**
204
+ * NUI 词法分析器
205
+ * 将源码分割为 Token 流,处理缩进敏感语法
206
+ */
207
+
208
+ /**
209
+ * 初始化词法分析器状态
210
+ */
211
+ declare function initTokenizerState(source: string): TokenizerState;
212
+ /**
213
+ * 读取行内容直到换行
214
+ * 用于处理函数体等内容
215
+ */
216
+ declare function readUntilNewline(state: TokenizerState): string;
217
+ /**
218
+ * 词法分析主函数
219
+ */
220
+ declare function tokenize(source: string): {
221
+ tokens: Token[];
222
+ errors: NuiCompilerError[];
223
+ };
224
+
225
+ /**
226
+ * NUI 语句解析器
227
+ * 解析 import、signal、function 声明
228
+ */
229
+
230
+ /**
231
+ * 解析 import 声明
232
+ * import Title from "./Title.nui"
233
+ */
234
+ declare function parseImportDeclaration(state: ParserState): ImportDeclaration | null;
235
+ /**
236
+ * 解析 signal 声明
237
+ * count = signal(0)
238
+ * users = asyncSignal(fetchUsers)
239
+ */
240
+ declare function parseSignalDeclaration(state: ParserState): SignalDeclaration | null;
241
+ /**
242
+ * 解析 function 声明
243
+ * function increment() { count.update(c => c + 1) }
244
+ */
245
+ declare function parseFunctionDeclaration(state: ParserState): FunctionDeclaration | null;
246
+ /**
247
+ * 语句解析结果
248
+ */
249
+ interface StatementParseResult {
250
+ imports: ImportDeclaration[];
251
+ signals: SignalDeclaration[];
252
+ functions: FunctionDeclaration[];
253
+ errors: NuiCompilerError[];
254
+ }
255
+ /**
256
+ * 解析所有语句
257
+ */
258
+ declare function parseStatements(tokens: Token[]): StatementParseResult;
259
+
260
+ /**
261
+ * NUI 模板解析器
262
+ * 解析 view 块的缩进式语法
263
+ */
264
+
265
+ /**
266
+ * 解析 view 块
267
+ */
268
+ declare function parseViewBlock(tokens: Token[]): {
269
+ view: ViewBlock | null;
270
+ errors: NuiCompilerError[];
271
+ };
272
+
273
+ /**
274
+ * NUI 模块代码生成器
275
+ * 将 NUI AST 转换为 JavaScript 模块代码
276
+ */
277
+
278
+ /**
279
+ * 生成模块代码
280
+ */
281
+ declare function generateModule(ast: NuiRootNode): NuiCompileResult;
282
+
283
+ /**
284
+ * compiler-nui
285
+ * NUI DSL 编译器
286
+ */
287
+
288
+ /**
289
+ * 解析 NUI 源码为 AST
290
+ */
291
+ declare function parse(source: string, options?: NuiParseOptions): NuiParseResult;
292
+ /**
293
+ * 编译 NUI 源码为 JavaScript 代码
294
+ */
295
+ declare function compile(source: string, options?: NuiParseOptions): NuiCompileResult;
296
+
297
+ export { KEYWORDS, NuiErrorCodes, NuiNodeTypes, TokenType, compile, generateModule, initTokenizerState, parse, parseFunctionDeclaration, parseImportDeclaration, parseSignalDeclaration, parseStatements, parseViewBlock, readUntilNewline, tokenize };
298
+ export type { FunctionDeclaration, ImportDeclaration, NuiCompileResult, NuiCompilerError, NuiParseOptions, NuiParseResult, NuiRootNode, ParserState, SignalDeclaration, StatementParseResult, StyleBlock, Token, TokenizerState, ViewBlock };
299
+ //# sourceMappingURL=compiler-nui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-nui.d.ts","sources":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","names":[]}
@@ -0,0 +1,2 @@
1
+ import{createTextNode as n,createInterpolationNode as e,createSimpleExpression as t,createIfBranchNode as o,createIfNode as r,createForNode as s,createElementNode as c,createDirectiveNode as i,createAttributeNode as u,createRoot as l,NodeTypes as f,createSourceLocation as E}from"@fluxion-ui/compiler-core";import{isNativeTag as N}from"@fluxion-ui/compiler-dom";var I=(n=>(n[n.INDENT=0]="INDENT",n[n.DEDENT=1]="DEDENT",n[n.NEWLINE=2]="NEWLINE",n[n.EOF=3]="EOF",n[n.IDENTIFIER=4]="IDENTIFIER",n[n.STRING=5]="STRING",n[n.NUMBER=6]="NUMBER",n[n.IMPORT=7]="IMPORT",n[n.FROM=8]="FROM",n[n.FUNCTION=9]="FUNCTION",n[n.IF=10]="IF",n[n.ELIF=11]="ELIF",n[n.ELSE=12]="ELSE",n[n.FOR=13]="FOR",n[n.IN=14]="IN",n[n.VIEW=15]="VIEW",n[n.STYLE=16]="STYLE",n[n.SIGNAL=17]="SIGNAL",n[n.ASYNC_SIGNAL=18]="ASYNC_SIGNAL",n[n.EQUALS=19]="EQUALS",n[n.COMMA=20]="COMMA",n[n.LPAREN=21]="LPAREN",n[n.RPAREN=22]="RPAREN",n[n.LBRACE=23]="LBRACE",n[n.RBRACE=24]="RBRACE",n[n.OPERATOR=25]="OPERATOR",n[n.AT=26]="AT",n[n.DOT=27]="DOT",n[n.INTERPOLATION_START=28]="INTERPOLATION_START",n[n.INTERPOLATION_END=29]="INTERPOLATION_END",n))(I||{}),a=(n=>(n[n.NUI_ROOT=0]="NUI_ROOT",n[n.IMPORT_DECLARATION=1]="IMPORT_DECLARATION",n[n.SIGNAL_DECLARATION=2]="SIGNAL_DECLARATION",n[n.FUNCTION_DECLARATION=3]="FUNCTION_DECLARATION",n[n.VIEW_BLOCK=4]="VIEW_BLOCK",n[n.STYLE_BLOCK=5]="STYLE_BLOCK",n))(a||{}),T=(n=>(n[n.UNEXPECTED_TOKEN=0]="UNEXPECTED_TOKEN",n[n.UNEXPECTED_EOF=1]="UNEXPECTED_EOF",n[n.INCONSISTENT_INDENT=2]="INCONSISTENT_INDENT",n[n.INVALID_STRING=3]="INVALID_STRING",n[n.INVALID_NUMBER=4]="INVALID_NUMBER",n[n.INVALID_IMPORT_SYNTAX=5]="INVALID_IMPORT_SYNTAX",n[n.INVALID_SIGNAL_SYNTAX=6]="INVALID_SIGNAL_SYNTAX",n[n.INVALID_FUNCTION_SYNTAX=7]="INVALID_FUNCTION_SYNTAX",n[n.INVALID_VIEW_SYNTAX=8]="INVALID_VIEW_SYNTAX",n[n.ELIF_WITHOUT_IF=9]="ELIF_WITHOUT_IF",n[n.ELSE_WITHOUT_IF=10]="ELSE_WITHOUT_IF",n[n.FOR_WITHOUT_IN=11]="FOR_WITHOUT_IN",n[n.UNTERMINATED_INTERPOLATION=12]="UNTERMINATED_INTERPOLATION",n[n.UNKNOWN_ERROR=13]="UNKNOWN_ERROR",n))(T||{});const p={import:7,from:8,function:9,if:10,elif:11,else:12,for:13,in:14,view:15,style:16,signal:17,asyncSignal:18},A="\n";function R(n,e,t){return{offset:n,line:e,column:t}}function h(n,e,t){return{start:n,end:e,source:t}}function d(n,e,t){const o=new SyntaxError(e);return o.code=n,o.loc=t,o}function O(n,e,t){return{type:n,value:e,loc:t}}function L(n){return{source:n,offset:0,line:1,column:1,indentStack:[0],tokens:[],errors:[]}}function _(n){return n.offset>=n.source.length?null:n.source[n.offset]}function D(n,e=1){const t=n.offset+e;return t>=n.source.length?null:n.source[t]}function S(n){const e=_(n);return null!==e&&(n.offset++,e===A?(n.line++,n.column=1):n.column++),e}function k(n){for(;" "===_(n);)S(n)}function y(n){let e=0;for(;"\t"===_(n);)e++,S(n);const t=_(n);return null===t||t===A?-1:e}function m(n,e,t){const o=[],r=n.indentStack[n.indentStack.length-1];if(e>r)n.indentStack.push(e),o.push(O(I.INDENT,"",t));else if(e<r){for(;n.indentStack.length>1&&n.indentStack[n.indentStack.length-1]>e;)n.indentStack.pop(),o.push(O(I.DEDENT,"",t));n.indentStack[n.indentStack.length-1]!==e&&n.errors.push(d(T.INCONSISTENT_INDENT,`缩进不一致:期望 ${n.indentStack[n.indentStack.length-1]} 个 Tab,但得到 ${e} 个`,t))}return o}function F(n){const e=h(R(n.offset,n.line,n.column),R(n.offset,n.line,n.column),""),t=S(n);let o="";for(;;){const r=_(n);if(null===r){n.errors.push(d(T.INVALID_STRING,"未终止的字符串",e));break}if(r===t){S(n);break}if("\\"===r){S(n);const e=_(n);if(null!==e)switch(S(n),e){case"n":o+="\n";break;case"t":o+="\t";break;case"r":o+="\r";break;case"\\":o+="\\";break;case'"':o+='"';break;case"'":o+="'";break;default:o+=e}}else o+=S(n)}const r=h(e.start,R(n.offset,n.line,n.column),"");return O(I.STRING,o,r)}function $(n){const e=n.offset,t=n.line,o=n.column;let r="",s=!1;for(;;){const e=_(n);if(null===e)break;if(e>="0"&&e<="9")r+=S(n);else{if("."!==e||s)break;{const e=D(n);if(!(null!==e&&e>="0"&&e<="9"))break;s=!0,r+=S(n)}}}const c=h(R(e,t,o),R(n.offset,n.line,n.column),"");return O(I.NUMBER,r,c)}function g(n){return/^[\p{L}]$/u.test(n)}function C(n){const e=n.offset,t=n.line,o=n.column;let r="";for(;;){const e=_(n);if(null===e)break;if(!(e>="a"&&e<="z"||e>="A"&&e<="Z"||e>="0"&&e<="9"||"_"===e||"$"===e||g(e)))break;r+=S(n)}const s=h(R(e,t,o),R(n.offset,n.line,n.column),""),c=p[r];return O(void 0!==c?c:I.IDENTIFIER,r,s)}function v(n){let e="";for(;;){const t=_(n);if(null===t||t===A)break;e+=S(n)}return e}function b(n){const e=L(n);let t=!0;for(;e.offset<n.length;){const n=_(e);if(t){if("\r"===n){S(e);continue}if(n===A){S(e);continue}const o=y(e);if(t=!1,-1===o){t=!0;continue}const r=m(e,o,h(R(e.offset,e.line,1),R(e.offset,e.line,1),""));e.tokens.push(...r);continue}if(n===A){const n=e.offset,o=e.line,r=e.column;S(e);const s=h(R(n,o,r),R(e.offset,e.line,e.column),"");e.tokens.push(O(I.NEWLINE,"\\n",s)),t=!0;continue}if("\r"===n){S(e);continue}if(" "===n){k(e);continue}if("/"===n&&"/"===D(e)){for(S(e),S(e);_(e)&&_(e)!==A;)S(e);continue}if("/"===n&&"*"===D(e)){for(S(e),S(e);_(e);){if("*"===_(e)&&"/"===D(e)){S(e),S(e);break}S(e)}continue}const o=e.offset,r=e.line,s=e.column;switch(n){case"\t":e.errors.push(d(T.INCONSISTENT_INDENT,"Tab 只能出现在行首",h(R(o,r,s),R(o+1,r,s+1),""))),S(e);break;case"@":S(e),e.tokens.push(O(I.AT,"@",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case"=":S(e),e.tokens.push(O(I.EQUALS,"=",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case",":S(e),e.tokens.push(O(I.COMMA,",",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case"(":S(e),e.tokens.push(O(I.LPAREN,"(",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case")":S(e),e.tokens.push(O(I.RPAREN,")",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case"{":S(e),e.tokens.push(O(I.LBRACE,"{",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case"}":S(e),e.tokens.push(O(I.RBRACE,"}",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case".":S(e),e.tokens.push(O(I.DOT,".",h(R(o,r,s),R(e.offset,r,s+1),"")));break;case"+":case"-":case"*":case"/":case"<":case">":case"!":case"&":case"|":case":":case";":case"?":case"%":S(e),e.tokens.push(O(I.OPERATOR,n,h(R(o,r,s),R(e.offset,r,s+1),"")));break;case'"':case"'":e.tokens.push(F(e));break;default:if(n>="0"&&n<="9"){e.tokens.push($(e));break}if(n>="a"&&n<="z"||n>="A"&&n<="Z"||"_"===n||"$"===n||g(n)){e.tokens.push(C(e));break}e.errors.push(d(T.UNEXPECTED_TOKEN,`意外的字符: ${n}`,h(R(o,r,s),R(o+1,r,s+1),""))),S(e)}}const o=h(R(e.offset,e.line,e.column),R(e.offset,e.line,e.column),"");for(;e.indentStack.length>1;)e.indentStack.pop(),e.tokens.push(O(I.DEDENT,"",o));return e.tokens.push(O(I.EOF,"",o)),{tokens:e.tokens,errors:e.errors}}function U(n,e,t){return{start:n,end:e,source:t}}function P(n){return{tokens:n,index:0,currentToken:n[0]||null,errors:[],indentLevel:0}}function W(n){return n.currentToken}function M(n){return n.index++,n.currentToken=n.index<n.tokens.length?n.tokens[n.index]:null,n.currentToken}function V(n,e){return n.currentToken?.type===e}function B(n,e,t){if(V(n,e)){const e=n.currentToken;return M(n),e}return n.errors.push(function(n,e,t){const o=new SyntaxError(e);return o.code=n,o.loc=t,o}(T.UNEXPECTED_TOKEN,t,n.currentToken?.loc)),null}function x(n){for(;V(n,I.NEWLINE);)M(n)}function G(n){for(;V(n,I.INDENT)||V(n,I.DEDENT);)M(n)}function X(n){const e=W(n);if(!e)return null;const t=e.loc;if(!V(n,I.IMPORT))return null;M(n);const o=B(n,I.IDENTIFIER,"import 语句需要指定导入的标识符");if(!o)return null;const r=o.value;B(n,I.FROM,'import 语句需要 "from" 关键词');const s=B(n,I.STRING,"import 语句需要指定来源路径");if(!s)return null;return{type:a.IMPORT_DECLARATION,identifier:r,source:s.value,loc:U(t.start,s.loc.end,"")}}function Y(n){const e=W(n);if(!e)return null;const t=e.loc;if(!V(n,I.IDENTIFIER))return null;const o=e.value;if(M(n),!V(n,I.EQUALS))return n.index--,n.currentToken=e,null;M(n);const r=V(n,I.ASYNC_SIGNAL);if(!r&&!V(n,I.SIGNAL))return n.index-=2,n.currentToken=n.tokens[n.index],null;M(n),B(n,I.LPAREN,"signal 声明需要括号");let s="";for(;W(n)&&!V(n,I.RPAREN);){const e=W(n);s+=e.type===I.STRING?`"${e.value}"`:e.value,M(n)}B(n,I.RPAREN,"signal 声明需要闭合括号");const c=W(n)?.loc||t;return{type:a.SIGNAL_DECLARATION,name:o,isAsync:r,initExpression:s,loc:U(t.start,c.end,"")}}function w(n){const e=W(n);if(!e)return null;const t=e.loc;if(!V(n,I.FUNCTION))return null;M(n);const o=B(n,I.IDENTIFIER,"函数声明需要指定函数名");if(!o)return null;const r=o.value,s=function(n){const e=[];if(!V(n,I.LPAREN))return e;for(M(n);!V(n,I.RPAREN);)if(V(n,I.IDENTIFIER)&&(e.push(W(n).value),M(n)),V(n,I.COMMA))M(n);else if(!V(n,I.RPAREN))break;return B(n,I.RPAREN,"函数参数列表需要闭合括号"),e}(n),c=function(n){if(!V(n,I.LBRACE))return"";M(n);let e="",t=1;for(;W(n)&&t>0;){const o=W(n);o.type===I.LBRACE?(t++,e+="{",M(n)):o.type===I.RBRACE?(t--,t>0&&(e+="}"),M(n)):o.type===I.NEWLINE?(e+="\n",M(n)):o.type===I.STRING?(e+=`"${o.value}"`,M(n)):(e+=o.value,M(n))}return e.trim()}(n),i=W(n)?.loc||t;return{type:a.FUNCTION_DECLARATION,name:r,params:s,body:c,loc:U(t.start,i.end,"")}}function K(n){const e=P(n),t=[],o=[],r=[];for(x(e);W(e)&&!V(e,I.EOF)&&(G(e),x(e),!V(e,I.EOF));){if(V(e,I.IMPORT)){const n=X(e);n&&t.push(n)}else if(V(e,I.FUNCTION)){const n=w(e);n&&r.push(n)}else if(V(e,I.IDENTIFIER)){const n=Y(e);n?o.push(n):M(e)}else M(e);x(e)}return{imports:t,signals:o,functions:r,errors:e.errors}}function Z(n){return!!/^[A-Z]/.test(n)||N(n)}function z(n,e,t){const o=new SyntaxError(e);return o.code=n,o.loc=t,o}function H(n){let e="",t=0;for(;W(n)&&!V(n,I.NEWLINE);){const o=W(n);if(o.type===I.INDENT||o.type===I.DEDENT)break;if(o.type===I.LPAREN?t++:o.type===I.RPAREN&&t--,0===t&&o.type===I.COMMA)break;if(e+=o.type===I.STRING?`"${o.value}"`:o.value,M(n),0===t){const e=W(n);if(e){if(e.type===I.AT)break;if(e.type===I.IDENTIFIER){const t=n.index;if(M(n),V(n,I.EQUALS)){n.index=t,n.currentToken=e;break}n.index=t,n.currentToken=e}}}}return e.trim()}function j(n,e){const t=W(n);if(!t||t.type!==I.IDENTIFIER)return null;const o=t.value;if(!Z(o))return null;M(n);const r=function(n){const e=[];for(;W(n)&&!V(n,I.NEWLINE);){const t=W(n);if(t.type===I.AT){const o=t;if(M(n),!V(n,I.IDENTIFIER)){n.errors.push(z(T.INVALID_VIEW_SYNTAX,"事件指令需要指定事件名",W(n)?.loc));break}const r=W(n).value;if(M(n),!V(n,I.EQUALS)){n.errors.push(z(T.INVALID_VIEW_SYNTAX,'事件指令需要 "="',W(n)?.loc));break}M(n);const s=H(n);if(!s){n.errors.push(z(T.INVALID_VIEW_SYNTAX,"事件指令需要指定处理函数",W(n)?.loc));break}e.push(i("on",s,r,[],o.loc));continue}if(t.type===I.IDENTIFIER){const o=t.value;if(M(n),V(n,I.EQUALS)){M(n);const r=W(n),s=r?.type===I.STRING;let c="";const i=W(n);(i?.type===I.STRING||i?.type===I.IDENTIFIER||i?.type===I.NUMBER)&&(c=i.value,M(n));const l=u(o,c,t.loc);l.isStatic=s,e.push(l);continue}n.index--,n.currentToken=t;break}break}return e}(n);return c(o,r,[],t.loc)}function Q(n,e){const s=W(n);if(!s||s.type!==I.IF)return null;const c=[];M(n);let i="";for(;W(n)&&!V(n,I.NEWLINE)&&!V(n,I.INDENT)&&!V(n,I.EOF);)i+=W(n).value,M(n);if(x(n),!V(n,I.INDENT))return n.errors.push(z(T.INVALID_VIEW_SYNTAX,"if 语句后需要缩进",W(n)?.loc)),null;M(n);const u=nn(n);for(c.push(o(u,i?t(i,!1):void 0,s.loc));V(n,I.ELIF);){M(n);let e="";for(;W(n)&&!V(n,I.NEWLINE)&&!V(n,I.INDENT)&&!V(n,I.EOF);)e+=W(n).value,M(n);if(x(n),!V(n,I.INDENT)){n.errors.push(z(T.INVALID_VIEW_SYNTAX,"elif 语句后需要缩进",W(n)?.loc));break}M(n);const r=nn(n);c.push(o(r,e?t(e,!1):void 0,W(n)?.loc))}if(V(n,I.ELSE))if(M(n),x(n),V(n,I.INDENT)){M(n);const e=nn(n);c.push(o(e,void 0,W(n)?.loc))}else n.errors.push(z(T.INVALID_VIEW_SYNTAX,"else 语句后需要缩进",W(n)?.loc));return r(c,s.loc)}function q(n,e){const o=W(n);if(!o||o.type!==I.FOR)return null;if(M(n),!V(n,I.IDENTIFIER))return n.errors.push(z(T.INVALID_VIEW_SYNTAX,"for 语句需要指定迭代变量",W(n)?.loc)),null;const r=W(n).value;if(M(n),!V(n,I.IN))return n.errors.push(z(T.FOR_WITHOUT_IN,'for 语句需要 "in" 关键词',W(n)?.loc)),null;M(n);let c="";for(;W(n)&&!V(n,I.NEWLINE)&&!V(n,I.INDENT)&&!V(n,I.EOF);)c+=W(n).value,M(n);if(x(n),!V(n,I.INDENT))return n.errors.push(z(T.INVALID_VIEW_SYNTAX,"for 语句后需要缩进",W(n)?.loc)),null;M(n);const i=nn(n);return s(t(c,!1),r,i,void 0,void 0,o.loc)}function J(o){const r=[];let s="",c=null;const i=()=>{s&&(r.push(n(s,c)),s="",c=null)};for(;W(o)&&!V(o,I.EOF)&&!(V(o,I.NEWLINE)||V(o,I.INDENT)||V(o,I.DEDENT)||V(o,I.RBRACE));){const n=W(o);if(n.type===I.LBRACE){i(),M(o);let s="";for(;W(o)&&!V(o,I.RBRACE)&&!V(o,I.NEWLINE)&&!V(o,I.EOF);){s+=W(o).value,M(o)}V(o,I.RBRACE)&&M(o),s&&r.push(e(t(s,!1),n.loc));continue}n.type!==I.IDENTIFIER&&n.type!==I.STRING&&n.type!==I.NUMBER&&n.type!==I.COMMA&&n.type!==I.OPERATOR&&n.type!==I.DOT||(c||(c=n.loc),s+=n.value),M(o)}return i(),r}function nn(o,r){const s=[];for(;W(o)&&!V(o,I.EOF);){if(V(o,I.DEDENT)){M(o);break}if(V(o,I.NEWLINE)){M(o);continue}if(V(o,I.INDENT)){M(o);continue}const r=W(o);if(r.type===I.IF){const n=Q(o);n&&s.push(n);continue}if(r.type!==I.ELIF&&r.type!==I.ELSE){if(r.type===I.FOR){const n=q(o);n&&s.push(n);continue}if(r.type!==I.IDENTIFIER){if(r.type===I.LBRACE){M(o);let n="";for(;W(o)&&!V(o,I.RBRACE)&&!V(o,I.NEWLINE)&&!V(o,I.EOF);){n+=W(o).value,M(o)}V(o,I.RBRACE)&&M(o),n&&s.push(e(t(n,!1),r.loc));continue}if(r.type===I.IDENTIFIER||r.type===I.NUMBER||r.type===I.STRING||r.type===I.COMMA||r.type===I.OPERATOR||r.type===I.DOT){let e="",t=r.loc;for(;W(o);){const n=W(o);if(n.type!==I.IDENTIFIER&&n.type!==I.NUMBER&&n.type!==I.STRING&&n.type!==I.COMMA&&n.type!==I.OPERATOR&&n.type!==I.DOT)break;e+=n.value,M(o)}e&&s.push(n(e,t));continue}M(o)}else if(Z(r.value)){const e=j(o);if(e){const t=J(o);if(/^[A-Z]/.test(e.tag)&&0===e.props.length&&t.length>0){const o=[n(e.tag,e.loc),...t];s.push(...o);continue}if(t.length>0&&(e.children=t),x(o),V(o,I.INDENT)){M(o);const n=nn(o);n.length>0&&(e.children=e.children&&e.children.length>0?[...e.children,...n]:n)}s.push(e)}}else{const n=J(o);s.push(...n)}}else o.errors.push(z(r.type===I.ELIF?T.ELIF_WITHOUT_IF:T.ELSE_WITHOUT_IF,(r.type===I.ELIF?"elif":"else")+" 必须紧跟在 if 或 elif 之后",r.loc)),M(o)}return s}function en(n){const e=P(n);let t=!1;for(;W(e)&&!V(e,I.EOF);){if(V(e,I.VIEW)){t=!0,M(e);break}M(e)}if(!t)return{view:null,errors:[]};if(x(e),!V(e,I.INDENT))return e.errors.push(z(T.INVALID_VIEW_SYNTAX,"view 块后需要缩进",W(e)?.loc)),{view:null,errors:e.errors};M(e);const o=nn(e);return{view:{type:a.VIEW_BLOCK,children:o,loc:{start:{offset:0,line:1,column:1},end:{offset:0,line:1,column:1},source:""}},errors:e.errors}}function tn(n,e){e.code+=`import ${n.identifier} from "${n.source}"\n`}function on(n,e){e.code+=`const ${n.name} = ${n.isAsync?"asyncSignal":"signal"}(${n.initExpression})\n`}function rn(n,e){e.code+=`function ${n.name}(${n.params.join(", ")}) { ${n.body} }\n`}function sn(n,e,t){const o=!N(n.tag),r=[];if(r.push(o?n.tag:`"${n.tag}"`),n.props.length>0){const e=function(n){const e=[];for(const t of n.props)if(t.type===f.ATTRIBUTE)if(t.value){const n=t.value.content;t.isStatic?e.push(`${t.name}: "${n}"`):/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(n)?e.push(`${t.name}: ${n}`):e.push(`${t.name}: "${n}"`)}else e.push(`${t.name}: true`);else if(t.type===f.DIRECTIVE&&"on"===t.name&&t.arg){const n=t.arg.content||t.arg,o=t.exp?t.exp.content:"undefined",r=`on${n.charAt(0).toUpperCase()}${n.slice(1)}`;e.push(`${r}: ${o}`)}if(0===e.length)return"null";return`{ ${e.join(", ")} }`}(n);r.push(e)}if(n.children.length>0){if(n.children.every(n=>n.type===f.TEXT)){const e=n.children.map(n=>n.content).join(" ");r.push(`"${e}"`)}else if(1===n.children.length){const e=cn(n.children[0]);r.push(e)}else{const e=[];for(let t=0;t<n.children.length;t++){const o=n.children[t],r=cn(o);if(o.type===f.TEXT&&t>0){}e.push(r)}r.push(`[${e.join(", ")}]`)}}return 1===r.length?`h(${r[0]})`:2===r.length?`h(${r[0]}, ${r[1]})`:`h(${r[0]}, ${r[1]}, ${r[2]})`}function cn(n,e,t){switch(n.type){case f.ELEMENT:return sn(n);case f.TEXT:return function(n){if(!n.includes("{"))return`"${n}"`;const e=[];let t=0;const o=/\{([^}]+)\}/g;let r;for(;null!==(r=o.exec(n));){r.index>t&&e.push(`"${n.slice(t,r.index)}"`);const o=r[1].trim();/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(o)?e.push(`${o}()`):e.push(o),t=r.index+r[0].length}t<n.length&&e.push(`"${n.slice(t)}"`);if(1===e.length)return e[0];return`[${e.join(", ")}]`}(n.content);case f.INTERPOLATION:const e=n.content.content||"";return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?`${e}()`:e;case f.IF:return function(n){const e=n.branches;if(0===e.length)return"null";let t="";for(let n=0;n<e.length;n++){const o=e[n];if(o.condition){const e=un(o.condition.content),r=ln(o.children);0===n?t=`${e} ? ${r}`:t+=` : ${e} ? ${r}`}else{t+=` : ${ln(o.children)}`}}return t}(n);case f.FOR:return function(n){const e=n.source.content,t=n.valueAlias,o=n.children,r=ln(o);return`${e}().map(${t} => ${r})`}(n);default:return"null"}}function un(n){let e=n;return e=e.replace(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b(?!\()/g,(n,e)=>["true","false","null","undefined","if","else","elif","for","in","view","style"].includes(e)?e:`${e}()`),e}function ln(n,e,t){if(0===n.length)return"null";if(1===n.length)return cn(n[0]);return`[${n.map(n=>cn(n)).join(", ")}]`}function fn(n){const e={code:"",indentLevel:0};[...n.imports,...n.signals,...n.functions].map(()=>null).filter(Boolean);for(const t of n.imports)tn(t,e);n.imports.length>0&&(e.code+="\n"),function(n,e,t,o){const r=new Set;n.length>0&&(r.add("signal"),n.some(n=>n.isAsync)&&r.add("asyncSignal")),t&&r.add("h"),r.size>0&&(o.code+=`import { ${Array.from(r).join(", ")} } from "@fluxion-ui/fluxion/runtime"\n`)}(n.signals,0,n.view,e),(n.signals.length>0||n.functions.length>0||n.view)&&(e.code+="\n");for(const t of n.signals)on(t,e);n.signals.length>0&&n.functions.length>0&&(e.code+="\n");for(const t of n.functions)rn(t,e);n.functions.length>0&&n.view&&(e.code+="\n"),n.view&&function(n,e){if(e.code+="function render() {\n",e.code+="\treturn ",0===n.children.length)e.code+="null";else if(1===n.children.length)e.code+=cn(n.children[0]);else{const t=n.children.map(n=>cn(n)).join(",\n\t\t");e.code+=`[\n\t\t${t}\n\t]`}e.code+="\n}\n"}(n.view,e),n.style&&function(n,e){if(!n.content.trim())return;const t=`style_${Buffer.from(n.content).toString("base64").slice(0,8)}`;e.code+="\n// 注入样式\n",e.code+=";(function() {\n",e.code+="\tif (typeof document !== 'undefined') {\n",e.code+=`\t\tconst style = document.getElementById('${t}')\n`,e.code+="\t\tif (!style) {\n",e.code+="\t\t\tconst el = document.createElement('style')\n",e.code+=`\t\t\tel.id = '${t}'\n`,e.code+=`\t\t\tel.textContent = \`${n.content.replace(/`/g,"\\`").replace(/\$/g,"\\$")}\`\n`,e.code+="\t\t\tdocument.head.appendChild(el)\n",e.code+="\t\t}\n",e.code+="\t}\n",e.code+="})()\n"}(n.style,e),n.view&&(e.code+="\nexport default { render }\n");const t=n.view?l(n.view.children):null;return{code:e.code,ast:n,templateAst:t,errors:[]}}function En(n,e={}){const{tokens:t,errors:o}=b(n);if(e.onError)for(const n of o)e.onError(n);const r=K(t),s=en(t),c=function(n,e){let t=null;for(const n of e)if(n.type===I.STYLE){t=n;break}if(!t)return{style:null,errors:[]};let o=t.loc.start.offset+5;for(;o<n.length&&"\n"!==n[o];)o++;o++,o<n.length&&"\t"===n[o]&&o++;let r="",s=o,c=!0;for(;s<n.length;){const e=n[s];"\n"===e?(r+=e,s++,c=!0):c&&"\t"===e?(s++,c=!1):(r+=e,s++,c=!1)}return{style:{type:a.STYLE_BLOCK,content:r.trim(),loc:t.loc},errors:[]}}(n,t);return{ast:{type:a.NUI_ROOT,imports:r.imports,signals:r.signals,functions:r.functions,view:s.view,style:c.style,loc:E({offset:0,line:1,column:1},{offset:n.length,line:1,column:1},n),source:n},errors:[...o,...r.errors,...s.errors,...c.errors]}}function Nn(n,e={}){const{ast:t,errors:o}=En(n,e),r=fn(t);return{...r,errors:[...o,...r.errors]}}export{p as KEYWORDS,T as NuiErrorCodes,a as NuiNodeTypes,I as TokenType,Nn as compile,fn as generateModule,L as initTokenizerState,En as parse,w as parseFunctionDeclaration,X as parseImportDeclaration,Y as parseSignalDeclaration,K as parseStatements,en as parseViewBlock,v as readUntilNewline,b as tokenize};
2
+ //# sourceMappingURL=compiler-nui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-nui.js","sources":["../src/types.ts","../src/tokenizer.ts","../src/parser/statement.ts","../src/parser/template.ts","../src/codegen/index.ts","../src/index.ts"],"sourcesContent":["/**\n * compiler-nui 类型定义\n * 定义 NUI DSL 的 Token 类型、AST 节点类型等\n */\n\nimport {\n\tNodeTypes,\n\tSourceLocation,\n\tPosition,\n\tTemplateChildNode,\n\tRootNode\n} from '@fluxion-ui/compiler-core'\n\n// ==================== Token 类型 ====================\n\n/**\n * Token 类型枚举\n */\nexport const enum TokenType {\n\t// 结构\n\tINDENT, // 缩进增加\n\tDEDENT, // 缩进减少\n\tNEWLINE, // 换行\n\tEOF, // 结束\n\n\t// 字面量\n\tIDENTIFIER, // 标识符\n\tSTRING, // 字符串 \"...\"\n\tNUMBER, // 数字\n\n\t// 关键词\n\tIMPORT, // import\n\tFROM, // from\n\tFUNCTION, // function\n\tIF, // if\n\tELIF, // elif\n\tELSE, // else\n\tFOR, // for\n\tIN, // in\n\tVIEW, // view\n\tSTYLE, // style\n\tSIGNAL, // signal\n\tASYNC_SIGNAL, // asyncSignal\n\n\t// 操作符\n\tEQUALS, // =\n\tCOMMA, // ,\n\tLPAREN, // (\n\tRPAREN, // )\n\tLBRACE, // {\n\tRBRACE, // }\n\tOPERATOR, // + - * / < > ! & | 等\n\n\t// 特殊\n\tAT, // @ 事件符号\n\tDOT, // .\n\tINTERPOLATION_START, // { 插值开始(行内)\n\tINTERPOLATION_END // } 插值结束(行内)\n}\n\n/**\n * Token 接口\n */\nexport interface Token {\n\ttype: TokenType\n\tvalue: string\n\tloc: SourceLocation\n}\n\n// ==================== NUI AST 节点类型 ====================\n\n/**\n * NUI AST 节点类型枚举\n */\nexport const enum NuiNodeTypes {\n\tNUI_ROOT, // NUI 根节点\n\tIMPORT_DECLARATION, // import 声明\n\tSIGNAL_DECLARATION, // signal 声明\n\tFUNCTION_DECLARATION,// function 声明\n\tVIEW_BLOCK, // view 块\n\tSTYLE_BLOCK // style 块\n}\n\n// ==================== NUI 根节点 ====================\n\n/**\n * NUI 根节点\n */\nexport interface NuiRootNode {\n\ttype: NuiNodeTypes.NUI_ROOT\n\t// import 声明列表\n\timports: ImportDeclaration[]\n\t// signal 声明列表\n\tsignals: SignalDeclaration[]\n\t// function 声明列表\n\tfunctions: FunctionDeclaration[]\n\t// view 块(可选)\n\tview: ViewBlock | null\n\t// style 块(可选)\n\tstyle: StyleBlock | null\n\t// 源码位置\n\tloc: SourceLocation\n\t// 原始源码\n\tsource: string\n}\n\n// ==================== Import 声明 ====================\n\n/**\n * import 声明\n * import Title from \"./Title.nui\"\n */\nexport interface ImportDeclaration {\n\ttype: NuiNodeTypes.IMPORT_DECLARATION\n\t// 导入的标识符\n\tidentifier: string\n\t// 导入来源路径\n\tsource: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Signal 声明 ====================\n\n/**\n * signal 声明\n * count = signal(0)\n * users = asyncSignal(fetchUsers)\n */\nexport interface SignalDeclaration {\n\ttype: NuiNodeTypes.SIGNAL_DECLARATION\n\t// 变量名\n\tname: string\n\t// 是否为 asyncSignal\n\tisAsync: boolean\n\t// 初始值表达式\n\tinitExpression: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Function 声明 ====================\n\n/**\n * function 声明\n * function increment() { count.update(c => c + 1) }\n */\nexport interface FunctionDeclaration {\n\ttype: NuiNodeTypes.FUNCTION_DECLARATION\n\t// 函数名\n\tname: string\n\t// 参数列表\n\tparams: string[]\n\t// 函数体(原始代码字符串)\n\tbody: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== View 块 ====================\n\n/**\n * view 块\n * 包含模板子节点\n */\nexport interface ViewBlock {\n\ttype: NuiNodeTypes.VIEW_BLOCK\n\t// 模板子节点(复用 compiler-core 的类型)\n\tchildren: TemplateChildNode[]\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== Style 块 ====================\n\n/**\n * style 块\n * 包含原始 CSS 代码\n */\nexport interface StyleBlock {\n\ttype: NuiNodeTypes.STYLE_BLOCK\n\t// CSS 内容\n\tcontent: string\n\t// 源码位置\n\tloc: SourceLocation\n}\n\n// ==================== 解析选项 ====================\n\n/**\n * NUI 解析选项\n */\nexport interface NuiParseOptions {\n\t// 文件名(用于错误提示)\n\tfilename?: string\n\t// 是否在浏览器环境\n\tisBrowser?: boolean\n\t// 错误回调\n\tonError?: (error: NuiCompilerError) => void\n}\n\n// ==================== 解析结果 ====================\n\n/**\n * NUI 解析结果\n */\nexport interface NuiParseResult {\n\t// 解析后的 AST\n\tast: NuiRootNode\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 编译结果 ====================\n\n/**\n * NUI 编译结果\n */\nexport interface NuiCompileResult {\n\t// 生成的代码\n\tcode: string\n\t// 解析后的 AST\n\tast: NuiRootNode\n\t// 模板 AST(compiler-core 格式)\n\ttemplateAst: RootNode | null\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 编译错误 ====================\n\n/**\n * NUI 编译错误\n */\nexport interface NuiCompilerError extends SyntaxError {\n\tcode: NuiErrorCodes\n\tloc?: SourceLocation\n}\n\n/**\n * NUI 错误代码\n */\nexport const enum NuiErrorCodes {\n\t// 词法错误\n\tUNEXPECTED_TOKEN,\n\tUNEXPECTED_EOF,\n\tINCONSISTENT_INDENT,\n\tINVALID_STRING,\n\tINVALID_NUMBER,\n\n\t// 语法错误\n\tINVALID_IMPORT_SYNTAX,\n\tINVALID_SIGNAL_SYNTAX,\n\tINVALID_FUNCTION_SYNTAX,\n\tINVALID_VIEW_SYNTAX,\n\tELIF_WITHOUT_IF,\n\tELSE_WITHOUT_IF,\n\tFOR_WITHOUT_IN,\n\tUNTERMINATED_INTERPOLATION,\n\n\t// 未知错误\n\tUNKNOWN_ERROR\n}\n\n// ==================== 词法分析器状态 ====================\n\n/**\n * 词法分析器状态\n */\nexport interface TokenizerState {\n\t// 源码\n\tsource: string\n\t// 当前位置\n\toffset: number\n\t// 当前行号\n\tline: number\n\t// 当前列号\n\tcolumn: number\n\t// 缩进栈\n\tindentStack: number[]\n\t// 当前 Token 列表\n\ttokens: Token[]\n\t// 错误列表\n\terrors: NuiCompilerError[]\n}\n\n// ==================== 解析器状态 ====================\n\n/**\n * 解析器状态\n */\nexport interface ParserState {\n\t// Token 列表\n\ttokens: Token[]\n\t// 当前 Token 索引\n\tindex: number\n\t// 当前 Token\n\tcurrentToken: Token | null\n\t// 错误列表\n\terrors: NuiCompilerError[]\n\t// 当前缩进层级\n\tindentLevel: number\n}\n\n// ==================== 工具函数 ====================\n\n/**\n * 关键词映射表\n */\nexport const KEYWORDS: Record<string, TokenType> = {\n\timport: TokenType.IMPORT,\n\tfrom: TokenType.FROM,\n\tfunction: TokenType.FUNCTION,\n\tif: TokenType.IF,\n\telif: TokenType.ELIF,\n\telse: TokenType.ELSE,\n\tfor: TokenType.FOR,\n\tin: TokenType.IN,\n\tview: TokenType.VIEW,\n\tstyle: TokenType.STYLE,\n\tsignal: TokenType.SIGNAL,\n\tasyncSignal: TokenType.ASYNC_SIGNAL\n}","/**\n * NUI 词法分析器\n * 将源码分割为 Token 流,处理缩进敏感语法\n */\n\nimport {\n\tTokenType,\n\tToken,\n\tTokenizerState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tKEYWORDS\n} from './types'\nimport {\n\tSourceLocation,\n\tPosition\n} from '@fluxion-ui/compiler-core'\nimport { warn } from '@fluxion-ui/shared'\n\n// ==================== 常量 ====================\n\n/**\n * Tab 字符\n */\nconst TAB = '\\t'\n\n/**\n * 换行符\n */\nconst NEWLINE = '\\n'\n\n/**\n * 回车符\n */\nconst CARRIAGE_RETURN = '\\r'\n\n/**\n * 空格字符\n */\nconst SPACE = ' '\n\n// ==================== 工具函数 ====================\n\n/**\n * 创建位置对象\n */\nfunction createPosition(\n\toffset: number,\n\tline: number,\n\tcolumn: number\n): Position {\n\treturn { offset, line, column }\n}\n\n/**\n * 创建源码位置对象\n */\nfunction createSourceLocation(\n\tstart: Position,\n\tend: Position,\n\tsource: string\n): SourceLocation {\n\treturn { start, end, source }\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n/**\n * 创建 Token\n */\nfunction createToken(\n\ttype: TokenType,\n\tvalue: string,\n\tloc: SourceLocation\n): Token {\n\treturn { type, value, loc }\n}\n\n// ==================== 词法分析器 ====================\n\n/**\n * 初始化词法分析器状态\n */\nexport function initTokenizerState(source: string): TokenizerState {\n\treturn {\n\t\tsource,\n\t\toffset: 0,\n\t\tline: 1,\n\t\tcolumn: 1,\n\t\tindentStack: [0],\n\t\ttokens: [],\n\t\terrors: []\n\t}\n}\n\n/**\n * 获取当前字符\n */\nfunction currentChar(state: TokenizerState): string | null {\n\tif (state.offset >= state.source.length) {\n\t\treturn null\n\t}\n\treturn state.source[state.offset]\n}\n\n/**\n * 向前看 n 个字符\n */\nfunction peekChar(state: TokenizerState, n: number = 1): string | null {\n\tconst offset = state.offset + n\n\tif (offset >= state.source.length) {\n\t\treturn null\n\t}\n\treturn state.source[offset]\n}\n\n/**\n * 前进一个字符\n */\nfunction advance(state: TokenizerState): string | null {\n\tconst char = currentChar(state)\n\tif (char !== null) {\n\t\tstate.offset++\n\t\tif (char === NEWLINE) {\n\t\t\tstate.line++\n\t\t\tstate.column = 1\n\t\t} else {\n\t\t\tstate.column++\n\t\t}\n\t}\n\treturn char\n}\n\n/**\n * 跳过空白字符(不包含换行)\n */\nfunction skipWhitespace(state: TokenizerState): void {\n\twhile (currentChar(state) === SPACE) {\n\t\tadvance(state)\n\t}\n}\n\n/**\n * 计算当前行的缩进(Tab 数量)\n * 仅在行首调用\n */\nfunction countIndent(state: TokenizerState): number {\n\tlet indent = 0\n\tconst startOffset = state.offset\n\n\twhile (currentChar(state) === TAB) {\n\t\tindent++\n\t\tadvance(state)\n\t}\n\n\t// 如果这一行是空行或注释行,返回 -1 表示忽略\n\tconst char = currentChar(state)\n\tif (char === null || char === NEWLINE) {\n\t\treturn -1\n\t}\n\n\treturn indent\n}\n\n/**\n * 处理缩进变化\n * 返回需要生成的 INDENT/DEDENT Token 数量\n */\nfunction handleIndent(\n\tstate: TokenizerState,\n\tcurrentIndent: number,\n\tloc: SourceLocation\n): Token[] {\n\tconst tokens: Token[] = []\n\tconst topIndent = state.indentStack[state.indentStack.length - 1]\n\n\tif (currentIndent > topIndent) {\n\t\t// 缩进增加\n\t\tstate.indentStack.push(currentIndent)\n\t\ttokens.push(createToken(TokenType.INDENT, '', loc))\n\t} else if (currentIndent < topIndent) {\n\t\t// 缩进减少,可能需要多个 DEDENT\n\t\twhile (\n\t\t\tstate.indentStack.length > 1 &&\n\t\t\tstate.indentStack[state.indentStack.length - 1] > currentIndent\n\t\t) {\n\t\t\tstate.indentStack.pop()\n\t\t\ttokens.push(createToken(TokenType.DEDENT, '', loc))\n\t\t}\n\n\t\t// 检查缩进是否匹配\n\t\tif (state.indentStack[state.indentStack.length - 1] !== currentIndent) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INCONSISTENT_INDENT,\n\t\t\t\t`缩进不一致:期望 ${state.indentStack[state.indentStack.length - 1]} 个 Tab,但得到 ${currentIndent} 个`,\n\t\t\t\tloc\n\t\t\t))\n\t\t}\n\t}\n\n\treturn tokens\n}\n\n/**\n * 读取字符串字面量\n */\nfunction readString(state: TokenizerState): Token {\n\tconst startLoc = createSourceLocation(\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\tconst quote = advance(state) // 读取起始引号\n\tlet value = ''\n\tconst start = state.offset\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_STRING,\n\t\t\t\t'未终止的字符串',\n\t\t\t\tstartLoc\n\t\t\t))\n\t\t\tbreak\n\t\t}\n\n\t\tif (char === quote) {\n\t\t\tadvance(state) // 读取结束引号\n\t\t\tbreak\n\t\t}\n\n\t\tif (char === '\\\\') {\n\t\t\tadvance(state)\n\t\t\tconst escaped = currentChar(state)\n\t\t\tif (escaped !== null) {\n\t\t\t\tadvance(state)\n\t\t\t\t// 处理转义字符\n\t\t\t\tswitch (escaped) {\n\t\t\t\t\tcase 'n':\n\t\t\t\t\t\tvalue += '\\n'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 't':\n\t\t\t\t\t\tvalue += '\\t'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'r':\n\t\t\t\t\t\tvalue += '\\r'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase '\\\\':\n\t\t\t\t\t\tvalue += '\\\\'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase '\"':\n\t\t\t\t\t\tvalue += '\"'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tvalue += \"'\"\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue += escaped\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tvalue += advance(state)\n\t\t}\n\t}\n\n\tconst endLoc = createSourceLocation(\n\t\tstartLoc.start,\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\treturn createToken(TokenType.STRING, value, endLoc)\n}\n\n/**\n * 读取数字字面量\n */\nfunction readNumber(state: TokenizerState): Token {\n\tconst startOffset = state.offset\n\tconst startLine = state.line\n\tconst startColumn = state.column\n\n\tlet value = ''\n\tlet hasDecimal = false\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) break\n\n\t\tif (char >= '0' && char <= '9') {\n\t\t\tvalue += advance(state)\n\t\t} else if (char === '.' && !hasDecimal) {\n\t\t\tconst next = peekChar(state)\n\t\t\tif (next !== null && next >= '0' && next <= '9') {\n\t\t\t\thasDecimal = true\n\t\t\t\tvalue += advance(state)\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst loc = createSourceLocation(\n\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\treturn createToken(TokenType.NUMBER, value, loc)\n}\n\n/**\n * 检查字符是否是 Unicode 字母(包括中文)\n * Unicode 字母范围:\n * - \\u4E00-\\u9FFF: CJK 统一汉字\n * - \\u3400-\\u4DBF: CJK 扩展 A\n * - \\u20000-\\u2A6DF: CJK 扩展 B (需要代理对)\n * - \\u2A700-\\u2B73F: CJK 扩展 C\n * - \\u2B740-\\u2B81F: CJK 扩展 D\n * - \\u2B820-\\u2CEAF: CJK 扩展 E\n * - \\u3040-\\u30FF: 日文假名\n * - \\uAC00-\\uD7AF: 韩文\n * - 其他 Unicode 字母(通过 \\p{L} 匹配)\n */\nfunction isUnicodeLetter(char: string): boolean {\n\t// 使用正则表达式匹配 Unicode 字母\n\t// \\p{L} 匹配所有 Unicode 字母类别\n\treturn /^[\\p{L}]$/u.test(char)\n}\n\n/**\n * 读取标识符或关键词\n */\nfunction readIdentifier(state: TokenizerState): Token {\n\tconst startOffset = state.offset\n\tconst startLine = state.line\n\tconst startColumn = state.column\n\n\tlet value = ''\n\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null) break\n\n\t\t// 标识符可以包含字母、数字、下划线、$、Unicode 字母(包括中文)\n\t\tif (\n\t\t\t(char >= 'a' && char <= 'z') ||\n\t\t\t(char >= 'A' && char <= 'Z') ||\n\t\t\t(char >= '0' && char <= '9') ||\n\t\t\tchar === '_' ||\n\t\t\tchar === '$' ||\n\t\t\tisUnicodeLetter(char)\n\t\t) {\n\t\t\tvalue += advance(state)\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst loc = createSourceLocation(\n\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\t// 检查是否为关键词\n\tconst keywordType = KEYWORDS[value]\n\tif (keywordType !== undefined) {\n\t\treturn createToken(keywordType, value, loc)\n\t}\n\n\treturn createToken(TokenType.IDENTIFIER, value, loc)\n}\n\n/**\n * 读取行内容直到换行\n * 用于处理函数体等内容\n */\nexport function readUntilNewline(state: TokenizerState): string {\n\tlet content = ''\n\twhile (true) {\n\t\tconst char = currentChar(state)\n\t\tif (char === null || char === NEWLINE) {\n\t\t\tbreak\n\t\t}\n\t\tcontent += advance(state)\n\t}\n\treturn content\n}\n\n/**\n * 词法分析主函数\n */\nexport function tokenize(source: string): {\n\ttokens: Token[]\n\terrors: NuiCompilerError[]\n} {\n\tconst state = initTokenizerState(source)\n\tlet atLineStart = true\n\tlet pendingIndent = 0\n\n\twhile (state.offset < source.length) {\n\t\tconst char = currentChar(state)\n\n\t\t// 处理行首缩进\n\t\tif (atLineStart) {\n\t\t\t// 跳过回车符\n\t\t\tif (char === CARRIAGE_RETURN) {\n\t\t\t\tadvance(state)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 处理换行(空行)\n\t\t\tif (char === NEWLINE) {\n\t\t\t\tadvance(state)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 计算缩进\n\t\t\tconst indent = countIndent(state)\n\t\t\tatLineStart = false\n\n\t\t\t// 空行,继续\n\t\t\tif (indent === -1) {\n\t\t\t\tatLineStart = true\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// 处理缩进变化\n\t\t\tconst loc = createSourceLocation(\n\t\t\t\tcreatePosition(state.offset, state.line, 1),\n\t\t\t\tcreatePosition(state.offset, state.line, 1),\n\t\t\t\t''\n\t\t\t)\n\t\t\tconst indentTokens = handleIndent(state, indent, loc)\n\t\t\tstate.tokens.push(...indentTokens)\n\n\t\t\t// 更新当前字符\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理换行\n\t\tif (char === NEWLINE) {\n\t\t\tconst startOffset = state.offset\n\t\t\tconst startLine = state.line\n\t\t\tconst startColumn = state.column\n\n\t\t\tadvance(state)\n\n\t\t\tconst loc = createSourceLocation(\n\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t\t\t''\n\t\t\t)\n\t\t\tstate.tokens.push(createToken(TokenType.NEWLINE, '\\\\n', loc))\n\t\t\tatLineStart = true\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过回车符\n\t\tif (char === CARRIAGE_RETURN) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过空格\n\t\tif (char === SPACE) {\n\t\t\tskipWhitespace(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理注释 // ...(跳过直到换行)\n\t\tif (char === '/' && peekChar(state) === '/') {\n\t\t\t// 跳过 //\n\t\t\tadvance(state)\n\t\t\tadvance(state)\n\t\t\t// 读取直到换行或文件结束\n\t\t\twhile (currentChar(state) && currentChar(state) !== NEWLINE) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 处理块注释 /* ... */\n\t\tif (char === '/' && peekChar(state) === '*') {\n\t\t\tadvance(state) // 跳过 /\n\t\t\tadvance(state) // 跳过 *\n\t\t\t// 读取直到 */\n\t\t\twhile (currentChar(state)) {\n\t\t\t\tif (currentChar(state) === '*' && peekChar(state) === '/') {\n\t\t\t\t\tadvance(state) // 跳过 *\n\t\t\t\t\tadvance(state) // 跳过 /\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 记录 Token 起始位置\n\t\tconst startOffset = state.offset\n\t\tconst startLine = state.line\n\t\tconst startColumn = state.column\n\n\t\t// 处理各种 Token\n\t\tswitch (char) {\n\t\t\tcase TAB:\n\t\t\t\t// Tab 只在行首有意义,其他位置视为错误\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INCONSISTENT_INDENT,\n\t\t\t\t\t'Tab 只能出现在行首',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(startOffset + 1, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tadvance(state)\n\t\t\t\tbreak\n\n\t\t\tcase '@':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.AT,\n\t\t\t\t\t'@',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '=':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.EQUALS,\n\t\t\t\t\t'=',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase ',':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.COMMA,\n\t\t\t\t\t',',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '(':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.LPAREN,\n\t\t\t\t\t'(',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase ')':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.RPAREN,\n\t\t\t\t\t')',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '{':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.LBRACE,\n\t\t\t\t\t'{',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '}':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.RBRACE,\n\t\t\t\t\t'}',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '.':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.DOT,\n\t\t\t\t\t'.',\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\t// 操作符:+ - * / < > ! & | : ; ? %\n\t\t\tcase '+':\n\t\t\tcase '-':\n\t\t\tcase '*':\n\t\t\tcase '/':\n\t\t\tcase '<':\n\t\t\tcase '>':\n\t\t\tcase '!':\n\t\t\tcase '&':\n\t\t\tcase '|':\n\t\t\tcase ':':\n\t\t\tcase ';':\n\t\t\tcase '?':\n\t\t\tcase '%':\n\t\t\t\tadvance(state)\n\t\t\t\tstate.tokens.push(createToken(\n\t\t\t\t\tTokenType.OPERATOR,\n\t\t\t\t\tchar,\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(state.offset, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tbreak\n\n\t\t\tcase '\"':\n\t\t\tcase \"'\":\n\t\t\t\tstate.tokens.push(readString(state))\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\t// 数字\n\t\t\t\tif (char >= '0' && char <= '9') {\n\t\t\t\t\tstate.tokens.push(readNumber(state))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t// 标识符或关键词(包括 Unicode 字母,如中文)\n\t\t\t\tif (\n\t\t\t\t\t(char >= 'a' && char <= 'z') ||\n\t\t\t\t\t(char >= 'A' && char <= 'Z') ||\n\t\t\t\t\tchar === '_' ||\n\t\t\t\t\tchar === '$' ||\n\t\t\t\t\tisUnicodeLetter(char)\n\t\t\t\t) {\n\t\t\t\t\tstate.tokens.push(readIdentifier(state))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t// 未知字符\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.UNEXPECTED_TOKEN,\n\t\t\t\t\t`意外的字符: ${char}`,\n\t\t\t\t\tcreateSourceLocation(\n\t\t\t\t\t\tcreatePosition(startOffset, startLine, startColumn),\n\t\t\t\t\t\tcreatePosition(startOffset + 1, startLine, startColumn + 1),\n\t\t\t\t\t\t''\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t\tadvance(state)\n\t\t}\n\t}\n\n\t// 生成剩余的 DEDENT\n\tconst endLoc = createSourceLocation(\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\tcreatePosition(state.offset, state.line, state.column),\n\t\t''\n\t)\n\n\twhile (state.indentStack.length > 1) {\n\t\tstate.indentStack.pop()\n\t\tstate.tokens.push(createToken(TokenType.DEDENT, '', endLoc))\n\t}\n\n\t// 添加 EOF\n\tstate.tokens.push(createToken(TokenType.EOF, '', endLoc))\n\n\treturn {\n\t\ttokens: state.tokens,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 语句解析器\n * 解析 import、signal、function 声明\n */\n\nimport {\n\tToken,\n\tTokenType,\n\tParserState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tNuiNodeTypes\n} from '../types'\nimport {\n\tSourceLocation,\n\tPosition\n} from '@fluxion-ui/compiler-core'\n\n// ==================== 工具函数 ====================\n\n/**\n * 创建位置对象\n */\nfunction createPosition(\n\toffset: number,\n\tline: number,\n\tcolumn: number\n): Position {\n\treturn { offset, line, column }\n}\n\n/**\n * 创建源码位置对象\n */\nfunction createSourceLocation(\n\tstart: Position,\n\tend: Position,\n\tsource: string\n): SourceLocation {\n\treturn { start, end, source }\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n/**\n * 初始化解析器状态\n */\nexport function initParserState(tokens: Token[]): ParserState {\n\treturn {\n\t\ttokens,\n\t\tindex: 0,\n\t\tcurrentToken: tokens[0] || null,\n\t\terrors: [],\n\t\tindentLevel: 0\n\t}\n}\n\n/**\n * 获取当前 Token\n */\nexport function currentToken(state: ParserState): Token | null {\n\treturn state.currentToken\n}\n\n/**\n * 获取下一个 Token(不移动)\n */\nexport function peekToken(state: ParserState): Token | null {\n\tconst nextIndex = state.index + 1\n\tif (nextIndex >= state.tokens.length) {\n\t\treturn null\n\t}\n\treturn state.tokens[nextIndex]\n}\n\n/**\n * 前进到下一个 Token\n */\nexport function advance(state: ParserState): Token | null {\n\tstate.index++\n\tif (state.index < state.tokens.length) {\n\t\tstate.currentToken = state.tokens[state.index]\n\t} else {\n\t\tstate.currentToken = null\n\t}\n\treturn state.currentToken\n}\n\n/**\n * 检查当前 Token 是否为指定类型\n */\nexport function isTokenType(state: ParserState, type: TokenType): boolean {\n\treturn state.currentToken?.type === type\n}\n\n/**\n * 期望当前 Token 为指定类型,否则报错\n */\nexport function expectToken(\n\tstate: ParserState,\n\ttype: TokenType,\n\terrorMessage: string\n): Token | null {\n\tif (isTokenType(state, type)) {\n\t\tconst token = state.currentToken\n\t\tadvance(state)\n\t\treturn token\n\t}\n\n\tstate.errors.push(createError(\n\t\tNuiErrorCodes.UNEXPECTED_TOKEN,\n\t\terrorMessage,\n\t\tstate.currentToken?.loc\n\t))\n\treturn null\n}\n\n/**\n * 跳过换行 Token\n */\nexport function skipNewlines(state: ParserState): void {\n\twhile (isTokenType(state, TokenType.NEWLINE)) {\n\t\tadvance(state)\n\t}\n}\n\n/**\n * 跳过缩进/缩进 Token\n */\nexport function skipIndent(state: ParserState): void {\n\twhile (\n\t\tisTokenType(state, TokenType.INDENT) ||\n\t\tisTokenType(state, TokenType.DEDENT)\n\t) {\n\t\tadvance(state)\n\t}\n}\n\n// ==================== Import 解析 ====================\n\n/**\n * 解析 import 声明\n * import Title from \"./Title.nui\"\n */\nexport function parseImportDeclaration(state: ParserState): ImportDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望 'import'\n\tif (!isTokenType(state, TokenType.IMPORT)) {\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望标识符\n\tconst identifierToken = expectToken(\n\t\tstate,\n\t\tTokenType.IDENTIFIER,\n\t\t'import 语句需要指定导入的标识符'\n\t)\n\tif (!identifierToken) return null\n\n\tconst identifier = identifierToken.value\n\n\t// 期望 'from'\n\texpectToken(state, TokenType.FROM, 'import 语句需要 \"from\" 关键词')\n\n\t// 期望字符串\n\tconst sourceToken = expectToken(\n\t\tstate,\n\t\tTokenType.STRING,\n\t\t'import 语句需要指定来源路径'\n\t)\n\tif (!sourceToken) return null\n\n\tconst source = sourceToken.value\n\n\tconst endLoc = sourceToken.loc\n\n\treturn {\n\t\ttype: NuiNodeTypes.IMPORT_DECLARATION,\n\t\tidentifier,\n\t\tsource,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== Signal 解析 ====================\n\n/**\n * 解析 signal 声明\n * count = signal(0)\n * users = asyncSignal(fetchUsers)\n */\nexport function parseSignalDeclaration(state: ParserState): SignalDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望标识符\n\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\treturn null\n\t}\n\tconst name = startToken.value\n\tadvance(state)\n\n\t// 期望 '='\n\tif (!isTokenType(state, TokenType.EQUALS)) {\n\t\t// 不是 signal 声明,回退\n\t\tstate.index--\n\t\tstate.currentToken = startToken\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 检查是 signal 还是 asyncSignal\n\tconst isAsync = isTokenType(state, TokenType.ASYNC_SIGNAL)\n\tif (!isAsync && !isTokenType(state, TokenType.SIGNAL)) {\n\t\t// 不是 signal 声明,回退并返回 null\n\t\tstate.index -= 2 // 回退到标识符位置(跳过标识符和 =)\n\t\tstate.currentToken = state.tokens[state.index]\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望 '('\n\texpectToken(state, TokenType.LPAREN, 'signal 声明需要括号')\n\n\t// 读取初始化表达式(直到 ')')\n\tlet initExpression = ''\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.RPAREN)) {\n\t\tconst token = currentToken(state)!\n\t\t// 字符串字面量需要加引号\n\t\tif (token.type === TokenType.STRING) {\n\t\t\tinitExpression += `\"${token.value}\"`\n\t\t} else {\n\t\t\tinitExpression += token.value\n\t\t}\n\t\tadvance(state)\n\t}\n\n\t// 期望 ')'\n\texpectToken(state, TokenType.RPAREN, 'signal 声明需要闭合括号')\n\n\tconst endLoc = currentToken(state)?.loc || startLoc\n\n\treturn {\n\t\ttype: NuiNodeTypes.SIGNAL_DECLARATION,\n\t\tname,\n\t\tisAsync,\n\t\tinitExpression,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== Function 解析 ====================\n\n/**\n * 解析函数参数列表\n */\nfunction parseFunctionParams(state: ParserState): string[] {\n\tconst params: string[] = []\n\n\t// 期望 '('\n\tif (!isTokenType(state, TokenType.LPAREN)) {\n\t\treturn params\n\t}\n\tadvance(state)\n\n\t// 解析参数\n\twhile (!isTokenType(state, TokenType.RPAREN)) {\n\t\tif (isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\tparams.push(currentToken(state)!.value)\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过逗号\n\t\tif (isTokenType(state, TokenType.COMMA)) {\n\t\t\tadvance(state)\n\t\t} else if (!isTokenType(state, TokenType.RPAREN)) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// 期望 ')'\n\texpectToken(state, TokenType.RPAREN, '函数参数列表需要闭合括号')\n\n\treturn params\n}\n\n/**\n * 解析函数体\n * 函数体从 '{' 开始到 '}' 结束,需要处理嵌套的大括号\n */\nfunction parseFunctionBody(state: ParserState): string {\n\t// 期望 '{'\n\tif (!isTokenType(state, TokenType.LBRACE)) {\n\t\treturn ''\n\t}\n\tadvance(state)\n\n\tlet body = ''\n\tlet braceDepth = 1\n\n\twhile (currentToken(state) && braceDepth > 0) {\n\t\tconst token = currentToken(state)!\n\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\tbraceDepth++\n\t\t\tbody += '{'\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.RBRACE) {\n\t\t\tbraceDepth--\n\t\t\tif (braceDepth > 0) {\n\t\t\t\tbody += '}'\n\t\t\t}\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.NEWLINE) {\n\t\t\tbody += '\\n'\n\t\t\tadvance(state)\n\t\t} else if (token.type === TokenType.STRING) {\n\t\t\t// 字符串字面量需要加引号\n\t\t\tbody += `\"${token.value}\"`\n\t\t\tadvance(state)\n\t\t} else {\n\t\t\tbody += token.value\n\t\t\tadvance(state)\n\t\t}\n\t}\n\n\treturn body.trim()\n}\n\n/**\n * 解析 function 声明\n * function increment() { count.update(c => c + 1) }\n */\nexport function parseFunctionDeclaration(state: ParserState): FunctionDeclaration | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken) return null\n\n\tconst startLoc = startToken.loc\n\n\t// 期望 'function'\n\tif (!isTokenType(state, TokenType.FUNCTION)) {\n\t\treturn null\n\t}\n\tadvance(state)\n\n\t// 期望函数名\n\tconst nameToken = expectToken(\n\t\tstate,\n\t\tTokenType.IDENTIFIER,\n\t\t'函数声明需要指定函数名'\n\t)\n\tif (!nameToken) return null\n\n\tconst name = nameToken.value\n\n\t// 解析参数\n\tconst params = parseFunctionParams(state)\n\n\t// 解析函数体\n\tconst body = parseFunctionBody(state)\n\n\tconst endLoc = currentToken(state)?.loc || startLoc\n\n\treturn {\n\t\ttype: NuiNodeTypes.FUNCTION_DECLARATION,\n\t\tname,\n\t\tparams,\n\t\tbody,\n\t\tloc: createSourceLocation(\n\t\t\tstartLoc.start,\n\t\t\tendLoc.end,\n\t\t\t''\n\t\t)\n\t}\n}\n\n// ==================== 语句解析入口 ====================\n\n/**\n * 语句解析结果\n */\nexport interface StatementParseResult {\n\timports: ImportDeclaration[]\n\tsignals: SignalDeclaration[]\n\tfunctions: FunctionDeclaration[]\n\terrors: NuiCompilerError[]\n}\n\n/**\n * 解析所有语句\n */\nexport function parseStatements(tokens: Token[]): StatementParseResult {\n\tconst state = initParserState(tokens)\n\n\tconst imports: ImportDeclaration[] = []\n\tconst signals: SignalDeclaration[] = []\n\tconst functions: FunctionDeclaration[] = []\n\n\t// 跳过开始的换行\n\tskipNewlines(state)\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 跳过缩进变化\n\t\tskipIndent(state)\n\t\tskipNewlines(state)\n\n\t\tif (isTokenType(state, TokenType.EOF)) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 尝试解析各种声明\n\t\tif (isTokenType(state, TokenType.IMPORT)) {\n\t\t\tconst decl = parseImportDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\timports.push(decl)\n\t\t\t}\n\t\t} else if (isTokenType(state, TokenType.FUNCTION)) {\n\t\t\tconst decl = parseFunctionDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\tfunctions.push(decl)\n\t\t\t}\n\t\t} else if (isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\t// 可能是 signal 声明\n\t\t\tconst decl = parseSignalDeclaration(state)\n\t\t\tif (decl) {\n\t\t\t\tsignals.push(decl)\n\t\t\t} else {\n\t\t\t\t// 无法识别的语句,跳过\n\t\t\t\tadvance(state)\n\t\t\t}\n\t\t} else {\n\t\t\t// 跳过无法识别的 Token\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过行尾\n\t\tskipNewlines(state)\n\t}\n\n\treturn {\n\t\timports,\n\t\tsignals,\n\t\tfunctions,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 模板解析器\n * 解析 view 块的缩进式语法\n */\n\nimport {\n\tToken,\n\tTokenType,\n\tParserState,\n\tNuiCompilerError,\n\tNuiErrorCodes,\n\tViewBlock,\n\tNuiNodeTypes\n} from '../types'\nimport {\n\tNodeTypes,\n\tElementTypes,\n\tSourceLocation,\n\tPosition,\n\tTemplateChildNode,\n\tElementNode,\n\tTextNode,\n\tInterpolationNode,\n\tIfNode,\n\tIfBranchNode,\n\tForNode,\n\tAttributeNode,\n\tDirectiveNode,\n\tSimpleExpressionNode\n} from '@fluxion-ui/compiler-core'\nimport {\n\tcreatePosition,\n\tcreateSourceLocation,\n\tcreateElementNode,\n\tcreateTextNode,\n\tcreateInterpolationNode,\n\tcreateAttributeNode,\n\tcreateDirectiveNode,\n\tcreateSimpleExpression,\n\tcreateIfNode,\n\tcreateIfBranchNode,\n\tcreateForNode\n} from '@fluxion-ui/compiler-core'\nimport { isNativeTag } from '@fluxion-ui/compiler-dom'\nimport {\n\tinitParserState,\n\tcurrentToken,\n\tadvance,\n\tisTokenType,\n\texpectToken,\n\tskipNewlines\n} from './statement'\n\n// ==================== 工具函数 ====================\n\n/**\n * 判断标识符是否是有效的元素标签\n * HTML 标签或组件(以大写字母开头)\n */\nfunction isValidElementTag(name: string): boolean {\n\t// 组件:以大写字母开头\n\tif (/^[A-Z]/.test(name)) {\n\t\treturn true\n\t}\n\t// HTML 标签\n\treturn isNativeTag(name)\n}\n\n/**\n * 创建编译错误\n */\nfunction createError(\n\tcode: NuiErrorCodes,\n\tmessage: string,\n\tloc?: SourceLocation\n): NuiCompilerError {\n\tconst error = new SyntaxError(message) as NuiCompilerError\n\terror.code = code\n\terror.loc = loc\n\treturn error\n}\n\n// ==================== 属性解析 ====================\n\n/**\n * 读取完整的表达式(支持函数调用)\n * 例如:switchTab(\"counter\") 或 reset 或 counter + 1\n */\nfunction readExpression(state: ParserState): string {\n\tlet expr = ''\n\tlet parenDepth = 0 // 括号嵌套深度\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.NEWLINE)) {\n\t\tconst token = currentToken(state)!\n\n\t\t// 遇到 INDENT 或 DEDENT 停止\n\t\tif (token.type === TokenType.INDENT || token.type === TokenType.DEDENT) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 跟踪括号深度\n\t\tif (token.type === TokenType.LPAREN) {\n\t\t\tparenDepth++\n\t\t} else if (token.type === TokenType.RPAREN) {\n\t\t\tparenDepth--\n\t\t}\n\n\t\t// 如果括号深度为 0 且遇到逗号,可能是下一个属性的分隔符\n\t\tif (parenDepth === 0 && token.type === TokenType.COMMA) {\n\t\t\tbreak\n\t\t}\n\n\t\t// 将 token 值添加到表达式\n\t\t// 字符串 token 需要加引号\n\t\tif (token.type === TokenType.STRING) {\n\t\t\t// 在函数参数中需要加引号\n\t\t\texpr += `\"${token.value}\"`\n\t\t} else {\n\t\t\texpr += token.value\n\t\t}\n\t\tadvance(state)\n\n\t\t// 如果括号深度归零且遇到某些 token,检查是否应该停止\n\t\tif (parenDepth === 0) {\n\t\t\t// 检查下一个 token,如果是属性开始符号(@ 或标识符后跟 =),停止\n\t\t\tconst next = currentToken(state)\n\t\t\tif (next) {\n\t\t\t\tif (next.type === TokenType.AT) {\n\t\t\t\t\t// 下一个是 @event 指令,停止\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif (next.type === TokenType.IDENTIFIER) {\n\t\t\t\t\t// 检查是否是 name=value 形式的属性\n\t\t\t\t\tconst savedIndex = state.index\n\t\t\t\t\tadvance(state)\n\t\t\t\t\tif (isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\t\t\t// 这是一个新属性,回退并停止\n\t\t\t\t\t\tstate.index = savedIndex\n\t\t\t\t\t\tstate.currentToken = next\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\t// 不是属性,继续,但需要恢复状态\n\t\t\t\t\tstate.index = savedIndex\n\t\t\t\t\tstate.currentToken = next\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn expr.trim()\n}\n\n/**\n * 解析元素属性\n * 支持:name=value, name=\"value\", @event=handler, @event=func(arg)\n */\nfunction parseElementProps(\n\tstate: ParserState\n): Array<AttributeNode | DirectiveNode> {\n\tconst props: Array<AttributeNode | DirectiveNode> = []\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.NEWLINE)) {\n\t\tconst token = currentToken(state)!\n\n\t\t// @event=handler 指令\n\t\tif (token.type === TokenType.AT) {\n\t\t\tconst atToken = token\n\t\t\tadvance(state) // 跳过 @\n\n\t\t\t// 读取事件名\n\t\t\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要指定事件名',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tconst eventName = currentToken(state)!.value\n\t\t\tadvance(state)\n\n\t\t\t// 期望 '='\n\t\t\tif (!isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要 \"=\"',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tadvance(state)\n\n\t\t\t// 读取完整的处理函数表达式(支持函数调用)\n\t\t\tconst handler = readExpression(state)\n\n\t\t\tif (!handler) {\n\t\t\t\tstate.errors.push(createError(\n\t\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t\t'事件指令需要指定处理函数',\n\t\t\t\t\tcurrentToken(state)?.loc\n\t\t\t\t))\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// 创建指令节点\n\t\t\tprops.push(createDirectiveNode(\n\t\t\t\t'on', // 事件指令名\n\t\t\t\thandler,\n\t\t\t\teventName,\n\t\t\t\t[],\n\t\t\t\tatToken.loc\n\t\t\t))\n\t\t\tcontinue\n\t\t}\n\n\t\t// name=value 属性\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\tconst attrName = token.value\n\t\t\tadvance(state)\n\n\t\t\t// 检查是否有值\n\t\t\tif (isTokenType(state, TokenType.EQUALS)) {\n\t\t\t\tadvance(state) // 跳过 '='\n\n\t\t\t\t// 检查第一个 token 是否是字符串\n\t\t\t\tconst firstToken = currentToken(state)\n\t\t\t\tconst isStaticValue = firstToken?.type === TokenType.STRING\n\n\t\t\t\t// 读取属性值(只读一个 token)\n\t\t\t\tlet attrValue = ''\n\t\t\t\tconst valueToken = currentToken(state)\n\n\t\t\t\tif (valueToken?.type === TokenType.STRING) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else if (valueToken?.type === TokenType.IDENTIFIER) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else if (valueToken?.type === TokenType.NUMBER) {\n\t\t\t\t\tattrValue = valueToken.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t}\n\n\t\t\t\t// 创建属性节点,标记是否为静态值\n\t\t\t\tconst attr = createAttributeNode(\n\t\t\t\t\tattrName,\n\t\t\t\t\tattrValue,\n\t\t\t\t\ttoken.loc\n\t\t\t\t)\n\t\t\t\t// 使用自定义属性标记静态值\n\t\t\t\t;(attr as any).isStatic = isStaticValue\n\t\t\t\tprops.push(attr)\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\t// 没有 '=' 表示这不是属性,可能是文本内容\n\t\t\t\t// 回退并停止解析属性\n\t\t\t\tstate.index--\n\t\t\t\tstate.currentToken = token\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// 无法识别的 Token,跳过\n\t\tbreak\n\t}\n\n\treturn props\n}\n\n// ==================== 文本解析 ====================\n\n/**\n * 解析文本行\n * 可能包含纯文本或插值表达式\n * 例如:hello {name}! 或 Count: {count}\n */\nfunction parseTextLine(\n\tstate: ParserState\n): Array<TextNode | InterpolationNode> {\n\tconst nodes: Array<TextNode | InterpolationNode> = []\n\tlet textContent = ''\n\n\t// 记录起始位置\n\tconst startLoc = currentToken(state)?.loc\n\n\t// 读取直到换行或文件结束\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tconst token = currentToken(state)!\n\n\t\t// 标识符可能是文本的一部分\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 字符串\n\t\tif (token.type === TokenType.STRING) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 数字\n\t\tif (token.type === TokenType.NUMBER) {\n\t\t\tif (textContent) {\n\t\t\t\ttextContent += ' '\n\t\t\t}\n\t\t\ttextContent += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 其他 Token 视为文本的一部分或跳过\n\t\tbreak\n\t}\n\n\t// 处理文本内容中的插值\n\t// 这里简化处理:将整个文本作为一个文本节点\n\t// 后续在 codegen 阶段处理插值\n\tif (textContent) {\n\t\tnodes.push(createTextNode(textContent, startLoc || undefined))\n\t}\n\n\treturn nodes\n}\n\n// ==================== 元素解析 ====================\n\n/**\n * 解析元素\n * tag [props...]\n */\nfunction parseElement(\n\tstate: ParserState,\n\tindentLevel: number\n): ElementNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.IDENTIFIER) {\n\t\treturn null\n\t}\n\n\tconst tagName = startToken.value\n\n\t// 检查是否是有效的元素标签\n\t// 如果不是 HTML 标签也不是组件(大写开头),返回 null\n\tif (!isValidElementTag(tagName)) {\n\t\treturn null\n\t}\n\n\tadvance(state)\n\n\t// 解析属性\n\tconst props = parseElementProps(state)\n\n\t// 创建元素节点\n\tconst element = createElementNode(\n\t\ttagName,\n\t\tprops,\n\t\t[],\n\t\tstartToken.loc\n\t)\n\n\treturn element\n}\n\n// ==================== 控制流解析 ====================\n\n/**\n * 解析 if 语句\n * if condition\n * ...\n * elif condition\n * ...\n * else\n * ...\n */\nfunction parseIfStatement(\n\tstate: ParserState,\n\tindentLevel: number\n): IfNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.IF) {\n\t\treturn null\n\t}\n\n\tconst branches: IfBranchNode[] = []\n\n\t// 解析 if 分支\n\tadvance(state) // 跳过 if\n\n\t// 读取条件表达式\n\tlet condition = ''\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tcondition += currentToken(state)!.value\n\t\tadvance(state)\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望缩进\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'if 语句后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析 if 分支的子节点\n\tconst ifChildren = parseChildren(state, indentLevel + 1)\n\n\tbranches.push(createIfBranchNode(\n\t\tifChildren,\n\t\tcondition ? createSimpleExpression(condition, false) : undefined,\n\t\tstartToken.loc\n\t))\n\n\t// 解析 elif 分支\n\twhile (isTokenType(state, TokenType.ELIF)) {\n\t\tadvance(state) // 跳过 elif\n\n\t\t// 读取条件表达式\n\t\tlet elifCondition = ''\n\t\twhile (\n\t\t\tcurrentToken(state) &&\n\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t) {\n\t\t\telifCondition += currentToken(state)!.value\n\t\t\tadvance(state)\n\t\t}\n\n\t\t// 跳过换行\n\t\tskipNewlines(state)\n\n\t\t// 期望缩进\n\t\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t'elif 语句后需要缩进',\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t\tbreak\n\t\t}\n\t\tadvance(state) // 跳过 INDENT\n\n\t\t// 解析 elif 分支的子节点\n\t\tconst elifChildren = parseChildren(state, indentLevel + 1)\n\n\t\tbranches.push(createIfBranchNode(\n\t\t\telifChildren,\n\t\t\telifCondition ? createSimpleExpression(elifCondition, false) : undefined,\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t}\n\n\t// 解析 else 分支\n\tif (isTokenType(state, TokenType.ELSE)) {\n\t\tadvance(state) // 跳过 else\n\n\t\t// 跳过换行\n\t\tskipNewlines(state)\n\n\t\t// 期望缩进\n\t\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t\t'else 语句后需要缩进',\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t} else {\n\t\t\tadvance(state) // 跳过 INDENT\n\n\t\t\t// 解析 else 分支的子节点\n\t\t\tconst elseChildren = parseChildren(state, indentLevel + 1)\n\n\t\t\tbranches.push(createIfBranchNode(\n\t\t\t\telseChildren,\n\t\t\t\tundefined, // else 无条件\n\t\t\t\tcurrentToken(state)?.loc\n\t\t\t))\n\t\t}\n\t}\n\n\treturn createIfNode(branches, startToken.loc)\n}\n\n/**\n * 解析 for 语句\n * for item in list\n * ...\n */\nfunction parseForStatement(\n\tstate: ParserState,\n\tindentLevel: number\n): ForNode | null {\n\tconst startToken = currentToken(state)\n\tif (!startToken || startToken.type !== TokenType.FOR) {\n\t\treturn null\n\t}\n\n\tadvance(state) // 跳过 for\n\n\t// 读取迭代变量\n\tif (!isTokenType(state, TokenType.IDENTIFIER)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'for 语句需要指定迭代变量',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tconst valueAlias = currentToken(state)!.value\n\tadvance(state)\n\n\t// 期望 'in'\n\tif (!isTokenType(state, TokenType.IN)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.FOR_WITHOUT_IN,\n\t\t\t'for 语句需要 \"in\" 关键词',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 in\n\n\t// 读取源表达式\n\tlet source = ''\n\twhile (\n\t\tcurrentToken(state) &&\n\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t!isTokenType(state, TokenType.INDENT) &&\n\t\t!isTokenType(state, TokenType.EOF)\n\t) {\n\t\tsource += currentToken(state)!.value\n\t\tadvance(state)\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望缩进\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'for 语句后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn null\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析子节点\n\tconst children = parseChildren(state, indentLevel + 1)\n\n\treturn createForNode(\n\t\tcreateSimpleExpression(source, false),\n\t\tvalueAlias,\n\t\tchildren,\n\t\tundefined, // keyAlias\n\t\tundefined, // indexAlias\n\t\tstartToken.loc\n\t)\n}\n\n// ==================== 子节点解析 ====================\n\n/**\n * 解析行内内容(元素后的文本和插值)\n * 例如:h1 {title} 或 p hello world\n */\nfunction parseInlineContent(state: ParserState): Array<TextNode | InterpolationNode> {\n\tconst nodes: Array<TextNode | InterpolationNode> = []\n\n\t// 收集连续的文本内容\n\tlet currentText = ''\n\tlet currentTextLoc: any = null\n\n\t// 辅助函数:将收集的文本推送到 nodes\n\tconst flushText = () => {\n\t\tif (currentText) {\n\t\t\tnodes.push(createTextNode(currentText, currentTextLoc))\n\t\t\tcurrentText = ''\n\t\t\tcurrentTextLoc = null\n\t\t}\n\t}\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 遇到换行、缩进、结束插值,停止\n\t\tif (\n\t\t\tisTokenType(state, TokenType.NEWLINE) ||\n\t\t\tisTokenType(state, TokenType.INDENT) ||\n\t\t\tisTokenType(state, TokenType.DEDENT) ||\n\t\t\tisTokenType(state, TokenType.RBRACE)\n\t\t) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst token = currentToken(state)!\n\n\t\t// 插值表达式 {expr}\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\t// 先刷新已收集的文本\n\t\t\tflushText()\n\n\t\t\tadvance(state) // 跳过 {\n\n\t\t\t// 读取插值内容\n\t\t\tlet expr = ''\n\t\t\twhile (\n\t\t\t\tcurrentToken(state) &&\n\t\t\t\t!isTokenType(state, TokenType.RBRACE) &&\n\t\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t\t) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\texpr += t.value\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 期望 }\n\t\t\tif (isTokenType(state, TokenType.RBRACE)) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 创建插值节点\n\t\t\tif (expr) {\n\t\t\t\tnodes.push(createInterpolationNode(\n\t\t\t\t\tcreateSimpleExpression(expr, false),\n\t\t\t\t\ttoken.loc\n\t\t\t\t))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 文本类 token:收集到 currentText\n\t\tif (\n\t\t\ttoken.type === TokenType.IDENTIFIER ||\n\t\t\ttoken.type === TokenType.STRING ||\n\t\t\ttoken.type === TokenType.NUMBER ||\n\t\t\ttoken.type === TokenType.COMMA ||\n\t\t\ttoken.type === TokenType.OPERATOR ||\n\t\t\ttoken.type === TokenType.DOT\n\t\t) {\n\t\t\t// 记录起始位置\n\t\t\tif (!currentTextLoc) {\n\t\t\t\tcurrentTextLoc = token.loc\n\t\t\t}\n\t\t\tcurrentText += token.value\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 其他 token 跳过\n\t\tadvance(state)\n\t}\n\n\t// 刷新剩余的文本\n\tflushText()\n\n\treturn nodes\n}\n\n/**\n * 解析子节点\n */\nfunction parseChildren(\n\tstate: ParserState,\n\tindentLevel: number\n): TemplateChildNode[] {\n\tconst children: TemplateChildNode[] = []\n\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\t// 检查是否到达当前块的结束(DEDENT)\n\t\tif (isTokenType(state, TokenType.DEDENT)) {\n\t\t\tadvance(state) // 消耗 DEDENT\n\t\t\tbreak\n\t\t}\n\n\t\t// 跳过换行\n\t\tif (isTokenType(state, TokenType.NEWLINE)) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// 跳过额外的 INDENT\n\t\tif (isTokenType(state, TokenType.INDENT)) {\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\tconst token = currentToken(state)!\n\n\t\t// if 语句\n\t\tif (token.type === TokenType.IF) {\n\t\t\tconst ifNode = parseIfStatement(state, indentLevel)\n\t\t\tif (ifNode) {\n\t\t\t\tchildren.push(ifNode)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// elif/else 不应该单独出现\n\t\tif (token.type === TokenType.ELIF || token.type === TokenType.ELSE) {\n\t\t\tstate.errors.push(createError(\n\t\t\t\ttoken.type === TokenType.ELIF\n\t\t\t\t\t? NuiErrorCodes.ELIF_WITHOUT_IF\n\t\t\t\t\t: NuiErrorCodes.ELSE_WITHOUT_IF,\n\t\t\t\t`${token.type === TokenType.ELIF ? 'elif' : 'else'} 必须紧跟在 if 或 elif 之后`,\n\t\t\t\ttoken.loc\n\t\t\t))\n\t\t\tadvance(state)\n\t\t\tcontinue\n\t\t}\n\n\t\t// for 语句\n\t\tif (token.type === TokenType.FOR) {\n\t\t\tconst forNode = parseForStatement(state, indentLevel)\n\t\t\tif (forNode) {\n\t\t\t\tchildren.push(forNode)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 元素或文本\n\t\tif (token.type === TokenType.IDENTIFIER) {\n\t\t\t// 检查是否是有效的元素标签\n\t\t\tif (isValidElementTag(token.value)) {\n\t\t\t\tconst element = parseElement(state, indentLevel)\n\t\t\t\tif (element) {\n\t\t\t\t\t// 先解析同一行的文本/插值内容\n\t\t\t\t\tconst inlineChildren = parseInlineContent(state)\n\n\t\t\t\t\t// 如果元素是组件(大写开头)、没有属性、且有行内文本内容\n\t\t\t\t\t// 则将整个行作为文本处理(用户想写的是文本,不是组件)\n\t\t\t\t\tif (/^[A-Z]/.test(element.tag) &&\n\t\t\t\t\t element.props.length === 0 &&\n\t\t\t\t\t inlineChildren.length > 0) {\n\t\t\t\t\t\t// 将标签名作为文本的一部分\n\t\t\t\t\t\tconst textNodes = [createTextNode(element.tag, element.loc), ...inlineChildren]\n\t\t\t\t\t\tchildren.push(...textNodes)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tif (inlineChildren.length > 0) {\n\t\t\t\t\t\telement.children = inlineChildren\n\t\t\t\t\t}\n\n\t\t\t\t\t// 检查是否有嵌套子节点(下一个 Token 是 INDENT)\n\t\t\t\t\tskipNewlines(state)\n\t\t\t\t\tif (isTokenType(state, TokenType.INDENT)) {\n\t\t\t\t\t\tadvance(state) // 消耗 INDENT\n\t\t\t\t\t\tconst elementChildren = parseChildren(state, indentLevel + 1)\n\t\t\t\t\t\t// 合并嵌套子节点\n\t\t\t\t\t\tif (elementChildren.length > 0) {\n\t\t\t\t\t\t\tif (element.children && element.children.length > 0) {\n\t\t\t\t\t\t\t\t// 如果已有行内内容,合并\n\t\t\t\t\t\t\t\telement.children = [...element.children, ...elementChildren]\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\telement.children = elementChildren\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchildren.push(element)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 不是有效的元素标签,作为文本处理\n\t\t\t\t// 收集同一行的所有文本内容\n\t\t\t\tconst textNodes = parseInlineContent(state)\n\t\t\t\tchildren.push(...textNodes)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 插值表达式 {expr} 作为独立的子节点\n\t\tif (token.type === TokenType.LBRACE) {\n\t\t\tadvance(state) // 跳过 {\n\n\t\t\t// 读取插值内容\n\t\t\tlet expr = ''\n\t\t\twhile (\n\t\t\t\tcurrentToken(state) &&\n\t\t\t\t!isTokenType(state, TokenType.RBRACE) &&\n\t\t\t\t!isTokenType(state, TokenType.NEWLINE) &&\n\t\t\t\t!isTokenType(state, TokenType.EOF)\n\t\t\t) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\texpr += t.value\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 期望 }\n\t\t\tif (isTokenType(state, TokenType.RBRACE)) {\n\t\t\t\tadvance(state)\n\t\t\t}\n\n\t\t\t// 创建插值节点\n\t\t\tif (expr) {\n\t\t\t\tchildren.push(createInterpolationNode(\n\t\t\t\t\tcreateSimpleExpression(expr, false),\n\t\t\t\t\ttoken.loc\n\t\t\t\t))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 文本类 token:收集连续的文本\n\t\tif (\n\t\t\ttoken.type === TokenType.IDENTIFIER ||\n\t\t\ttoken.type === TokenType.NUMBER ||\n\t\t\ttoken.type === TokenType.STRING ||\n\t\t\ttoken.type === TokenType.COMMA ||\n\t\t\ttoken.type === TokenType.OPERATOR ||\n\t\t\ttoken.type === TokenType.DOT\n\t\t) {\n\t\t\tlet textContent = ''\n\t\t\tlet textLoc: any = token.loc\n\n\t\t\t// 收集连续的文本 token\n\t\t\twhile (currentToken(state)) {\n\t\t\t\tconst t = currentToken(state)!\n\t\t\t\tif (\n\t\t\t\t\tt.type === TokenType.IDENTIFIER ||\n\t\t\t\t\tt.type === TokenType.NUMBER ||\n\t\t\t\t\tt.type === TokenType.STRING ||\n\t\t\t\t\tt.type === TokenType.COMMA ||\n\t\t\t\t\tt.type === TokenType.OPERATOR ||\n\t\t\t\t\tt.type === TokenType.DOT\n\t\t\t\t) {\n\t\t\t\t\ttextContent += t.value\n\t\t\t\t\tadvance(state)\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (textContent) {\n\t\t\t\tchildren.push(createTextNode(textContent, textLoc))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// 无法识别的 Token,跳过\n\t\tadvance(state)\n\t}\n\n\treturn children\n}\n\n// ==================== View 块解析 ====================\n\n/**\n * 解析 view 块\n */\nexport function parseViewBlock(tokens: Token[]): {\n\tview: ViewBlock | null\n\terrors: NuiCompilerError[]\n} {\n\tconst state = initParserState(tokens)\n\n\t// 找到 view 关键词\n\tlet foundView = false\n\twhile (currentToken(state) && !isTokenType(state, TokenType.EOF)) {\n\t\tif (isTokenType(state, TokenType.VIEW)) {\n\t\t\tfoundView = true\n\t\t\tadvance(state) // 跳过 view\n\t\t\tbreak\n\t\t}\n\t\tadvance(state)\n\t}\n\n\tif (!foundView) {\n\t\treturn {\n\t\t\tview: null,\n\t\t\terrors: []\n\t\t}\n\t}\n\n\t// 跳过换行\n\tskipNewlines(state)\n\n\t// 期望 INDENT\n\tif (!isTokenType(state, TokenType.INDENT)) {\n\t\tstate.errors.push(createError(\n\t\t\tNuiErrorCodes.INVALID_VIEW_SYNTAX,\n\t\t\t'view 块后需要缩进',\n\t\t\tcurrentToken(state)?.loc\n\t\t))\n\t\treturn {\n\t\t\tview: null,\n\t\t\terrors: state.errors\n\t\t}\n\t}\n\tadvance(state) // 跳过 INDENT\n\n\t// 解析子节点\n\tconst children = parseChildren(state, 1)\n\n\tconst viewBlock: ViewBlock = {\n\t\ttype: NuiNodeTypes.VIEW_BLOCK,\n\t\tchildren,\n\t\tloc: {\n\t\t\tstart: { offset: 0, line: 1, column: 1 },\n\t\t\tend: { offset: 0, line: 1, column: 1 },\n\t\t\tsource: ''\n\t\t}\n\t}\n\n\treturn {\n\t\tview: viewBlock,\n\t\terrors: state.errors\n\t}\n}","/**\n * NUI 模块代码生成器\n * 将 NUI AST 转换为 JavaScript 模块代码\n */\n\nimport {\n\tNuiRootNode,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tViewBlock,\n\tStyleBlock,\n\tNuiCompileResult\n} from '../types'\nimport {\n\tNodeTypes,\n\tElementNode,\n\tTextNode,\n\tInterpolationNode,\n\tIfNode,\n\tForNode,\n\tTemplateChildNode,\n\tRootNode,\n\tcreateRoot\n} from '@fluxion-ui/compiler-core'\nimport { isNativeTag } from '@fluxion-ui/compiler-dom'\nimport { warn } from '@fluxion-ui/shared'\n\n// ==================== 代码生成上下文 ====================\n\n/**\n * 代码生成上下文\n */\ninterface ModuleCodegenContext {\n\t// 生成的代码\n\tcode: string\n\t// 缩进级别\n\tindentLevel: number\n}\n\n/**\n * 创建代码生成上下文\n */\nfunction createModuleCodegenContext(): ModuleCodegenContext {\n\treturn {\n\t\tcode: '',\n\t\tindentLevel: 0\n\t}\n}\n\n// ==================== 缩进辅助 ====================\n\n/**\n * 获取缩进字符串\n */\nfunction indent(level: number): string {\n\treturn '\\t'.repeat(level)\n}\n\n// ==================== Import 代码生成 ====================\n\n/**\n * 生成用户 import 语句\n */\nfunction genImportDeclaration(\n\tdecl: ImportDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += `import ${decl.identifier} from \"${decl.source}\"\\n`\n}\n\n/**\n * 生成运行时 import 语句\n */\nfunction genRuntimeImports(\n\tsignals: SignalDeclaration[],\n\tfunctions: FunctionDeclaration[],\n\tview: ViewBlock | null,\n\tctx: ModuleCodegenContext\n): void {\n\tconst imports: Set<string> = new Set()\n\n\t// signal 相关\n\tif (signals.length > 0) {\n\t\timports.add('signal')\n\t\t// 检查是否有 asyncSignal\n\t\tif (signals.some(s => s.isAsync)) {\n\t\t\timports.add('asyncSignal')\n\t\t}\n\t}\n\n\t// render 相关\n\tif (view) {\n\t\timports.add('h')\n\t}\n\n\tif (imports.size > 0) {\n\t\tctx.code += `import { ${Array.from(imports).join(', ')} } from \"@fluxion-ui/fluxion/runtime\"\\n`\n\t}\n}\n\n// ==================== Signal 代码生成 ====================\n\n/**\n * 生成 signal 声明\n */\nfunction genSignalDeclaration(\n\tdecl: SignalDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tconst keyword = decl.isAsync ? 'asyncSignal' : 'signal'\n\tctx.code += `const ${decl.name} = ${keyword}(${decl.initExpression})\\n`\n}\n\n// ==================== Function 代码生成 ====================\n\n/**\n * 生成函数声明\n */\nfunction genFunctionDeclaration(\n\tdecl: FunctionDeclaration,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += `function ${decl.name}(${decl.params.join(', ')}) { ${decl.body} }\\n`\n}\n\n// ==================== Render 函数代码生成 ====================\n\n/**\n * 生成元素节点代码\n */\nfunction genElementNode(\n\tnode: ElementNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst indentStr = indent(indentLevel)\n\tconst isComponent = !isNativeTag(node.tag)\n\n\t// 构建参数\n\tconst args: string[] = []\n\n\t// 第一个参数:标签名或组件\n\tif (isComponent) {\n\t\targs.push(node.tag) // 组件直接使用标识符\n\t} else {\n\t\targs.push(`\"${node.tag}\"`) // 原生标签使用字符串\n\t}\n\n\t// 第二个参数:props\n\tif (node.props.length > 0) {\n\t\tconst propsObj = genPropsObject(node)\n\t\targs.push(propsObj)\n\t}\n\n\t// 第三个参数:children\n\tif (node.children.length > 0) {\n\t\t// 检查是否所有子节点都是文本节点(没有插值)\n\t\tconst allText = node.children.every(\n\t\t\tchild => child.type === NodeTypes.TEXT\n\t\t)\n\n\t\tif (allText) {\n\t\t\t// 合并所有文本为一个字符串\n\t\t\tconst combinedText = (node.children as TextNode[])\n\t\t\t\t.map(child => child.content)\n\t\t\t\t.join(' ')\n\t\t\targs.push(`\"${combinedText}\"`)\n\t\t} else if (node.children.length === 1) {\n\t\t\tconst childCode = genChildNode(node.children[0], ctx, indentLevel)\n\t\t\targs.push(childCode)\n\t\t} else {\n\t\t\t// 混合内容:文本和插值\n\t\t\t// 需要处理文本节点之间的空格\n\t\t\tconst childrenParts: string[] = []\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i]\n\t\t\t\tconst childCode = genChildNode(child, ctx, indentLevel)\n\n\t\t\t\t// 如果当前是文本节点,且前一个也是文本节点,需要添加空格连接\n\t\t\t\tif (child.type === NodeTypes.TEXT && i > 0) {\n\t\t\t\t\tconst prevChild = node.children[i - 1]\n\t\t\t\t\tif (prevChild.type === NodeTypes.TEXT) {\n\t\t\t\t\t\t// 两个相邻的文本节点,用 + 连接并添加空格\n\t\t\t\t\t\t// 但由于我们分别处理,这里不需要额外处理\n\t\t\t\t\t\t// 因为每个文本节点已经用引号包裹\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tchildrenParts.push(childCode)\n\t\t\t}\n\t\t\targs.push(`[${childrenParts.join(', ')}]`)\n\t\t}\n\t}\n\n\t// 生成 h 调用\n\tif (args.length === 1) {\n\t\treturn `h(${args[0]})`\n\t} else if (args.length === 2) {\n\t\treturn `h(${args[0]}, ${args[1]})`\n\t} else {\n\t\treturn `h(${args[0]}, ${args[1]}, ${args[2]})`\n\t}\n}\n\n/**\n * 生成 props 对象代码\n */\nfunction genPropsObject(node: ElementNode): string {\n\tconst props: string[] = []\n\n\tfor (const prop of node.props) {\n\t\tif (prop.type === NodeTypes.ATTRIBUTE) {\n\t\t\t// 普通属性\n\t\t\tif (prop.value) {\n\t\t\t\tconst value = prop.value.content\n\t\t\t\t// 检查是否标记为静态值(字符串字面量)\n\t\t\t\tconst isStatic = (prop as any).isStatic\n\t\t\t\tif (isStatic) {\n\t\t\t\t\t// 静态字符串值,加引号\n\t\t\t\t\tprops.push(`${prop.name}: \"${value}\"`)\n\t\t\t\t} else if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(value)) {\n\t\t\t\t\t// 标识符(变量引用),直接使用\n\t\t\t\t\tprops.push(`${prop.name}: ${value}`)\n\t\t\t\t} else {\n\t\t\t\t\t// 其他情况,加引号\n\t\t\t\t\tprops.push(`${prop.name}: \"${value}\"`)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tprops.push(`${prop.name}: true`)\n\t\t\t}\n\t\t} else if (prop.type === NodeTypes.DIRECTIVE) {\n\t\t\t// 指令(主要是事件)\n\t\t\tif (prop.name === 'on' && prop.arg) {\n\t\t\t\tconst eventName = (prop.arg as any).content || prop.arg\n\t\t\t\tconst handler = prop.exp ? (prop.exp as any).content : 'undefined'\n\t\t\t\t// 转换事件名:click -> onClick\n\t\t\t\tconst handlerName = `on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`\n\t\t\t\tprops.push(`${handlerName}: ${handler}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (props.length === 0) {\n\t\treturn 'null'\n\t}\n\n\treturn `{ ${props.join(', ')} }`\n}\n\n/**\n * 生成子节点代码\n */\nfunction genChildNode(\n\tnode: TemplateChildNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tswitch (node.type) {\n\t\tcase NodeTypes.ELEMENT:\n\t\t\treturn genElementNode(node as ElementNode, ctx, indentLevel)\n\n\t\tcase NodeTypes.TEXT:\n\t\t\tconst textContent = (node as TextNode).content\n\t\t\t// 处理插值表达式 {xxx}\n\t\t\treturn genTextWithInterpolation(textContent)\n\n\t\tcase NodeTypes.INTERPOLATION:\n\t\t\tconst exp = (node as InterpolationNode).content\n\t\t\tconst exprContent = (exp as any).content || ''\n\t\t\t// 如果是简单标识符,添加 () 来调用 signal\n\t\t\tif (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(exprContent)) {\n\t\t\t\treturn `${exprContent}()`\n\t\t\t}\n\t\t\treturn exprContent\n\n\t\tcase NodeTypes.IF:\n\t\t\treturn genIfNode(node as IfNode, ctx, indentLevel)\n\n\t\tcase NodeTypes.FOR:\n\t\t\treturn genForNode(node as ForNode, ctx, indentLevel)\n\n\t\tdefault:\n\t\t\treturn 'null'\n\t}\n}\n\n/**\n * 处理包含插值表达式的文本\n * 例如:hello {name}! -> [\"hello \", name(), \"!\"]\n * 根据设计文档,{count} 被转换为 count() 来读取 signal 的值\n */\nfunction genTextWithInterpolation(text: string): string {\n\t// 检查是否包含插值\n\tif (!text.includes('{')) {\n\t\treturn `\"${text}\"`\n\t}\n\n\t// 解析插值表达式\n\tconst parts: string[] = []\n\tlet lastIndex = 0\n\tconst regex = /\\{([^}]+)\\}/g\n\tlet match\n\n\twhile ((match = regex.exec(text)) !== null) {\n\t\t// 添加前面的文本\n\t\tif (match.index > lastIndex) {\n\t\t\tparts.push(`\"${text.slice(lastIndex, match.index)}\"`)\n\t\t}\n\t\t// 添加插值表达式,转换为 signal 调用\n\t\t// 根据设计文档:{count} → count()\n\t\tconst expr = match[1].trim()\n\t\t// 如果是简单标识符,添加 () 调用\n\t\tif (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(expr)) {\n\t\t\tparts.push(`${expr}()`)\n\t\t} else {\n\t\t\t// 复杂表达式,保持原样(可能已经包含函数调用)\n\t\t\tparts.push(expr)\n\t\t}\n\t\tlastIndex = match.index + match[0].length\n\t}\n\n\t// 添加剩余的文本\n\tif (lastIndex < text.length) {\n\t\tparts.push(`\"${text.slice(lastIndex)}\"`)\n\t}\n\n\tif (parts.length === 1) {\n\t\treturn parts[0]\n\t}\n\n\treturn `[${parts.join(', ')}]`\n}\n\n/**\n * 将条件表达式中的 Signal 标识符转换为函数调用\n * 例如:loading -> loading()\n * 例如:status == \"loading\" -> status() == \"loading\"\n */\nfunction convertSignalAccess(condition: string): string {\n\t// 处理比较操作符周围的标识符\n\t// 匹配模式:标识符(不在引号内)后面跟着操作符\n\tconst operators = ['==', '!=', '===', '!==', '<', '>', '<=', '>=', '&&', '||']\n\n\tlet result = condition\n\n\t// 简单方法:将独立的标识符转换为函数调用\n\t// 匹配:单词边界开始的标识符,后面不是 ( (说明不是函数调用)\n\tresult = result.replace(/\\b([a-zA-Z_$][a-zA-Z0-9_$]*)\\b(?!\\()/g, (match, ident) => {\n\t\t// 排除关键字和字面量\n\t\tconst keywords = ['true', 'false', 'null', 'undefined', 'if', 'else', 'elif', 'for', 'in', 'view', 'style']\n\t\tif (keywords.includes(ident)) {\n\t\t\treturn ident\n\t\t}\n\t\treturn `${ident}()`\n\t})\n\n\treturn result\n}\n\n/**\n * 生成 if 节点代码\n */\nfunction genIfNode(\n\tnode: IfNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst branches = node.branches\n\n\tif (branches.length === 0) {\n\t\treturn 'null'\n\t}\n\n\t// 生成三元表达式链\n\tlet code = ''\n\n\tfor (let i = 0; i < branches.length; i++) {\n\t\tconst branch = branches[i]\n\n\t\tif (branch.condition) {\n\t\t\t// if 或 elif 分支\n\t\t\tconst rawCondition = (branch.condition as any).content\n\t\t\t// 将条件中的 Signal 标识符转换为函数调用\n\t\t\tconst condition = convertSignalAccess(rawCondition)\n\t\t\tconst consequent = genBranchChildren(branch.children, ctx, indentLevel)\n\n\t\t\tif (i === 0) {\n\t\t\t\t// 第一个分支\n\t\t\t\tcode = `${condition} ? ${consequent}`\n\t\t\t} else {\n\t\t\t\t// 后续分支\n\t\t\t\tcode += ` : ${condition} ? ${consequent}`\n\t\t\t}\n\t\t} else {\n\t\t\t// else 分支\n\t\t\tconst alternate = genBranchChildren(branch.children, ctx, indentLevel)\n\t\t\tcode += ` : ${alternate}`\n\t\t}\n\t}\n\n\treturn code\n}\n\n/**\n * 生成分支子节点代码\n */\nfunction genBranchChildren(\n\tchildren: TemplateChildNode[],\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tif (children.length === 0) {\n\t\treturn 'null'\n\t}\n\n\tif (children.length === 1) {\n\t\treturn genChildNode(children[0], ctx, indentLevel)\n\t}\n\n\tconst childrenCode = children\n\t\t.map(child => genChildNode(child, ctx, indentLevel))\n\t\t.join(', ')\n\treturn `[${childrenCode}]`\n}\n\n/**\n * 生成 for 节点代码\n */\nfunction genForNode(\n\tnode: ForNode,\n\tctx: ModuleCodegenContext,\n\tindentLevel: number\n): string {\n\tconst source = node.source.content\n\tconst valueAlias = node.valueAlias\n\tconst children = node.children\n\n\t// 生成 map 回调\n\tconst childrenCode = genBranchChildren(children, ctx, indentLevel + 1)\n\n\treturn `${source}().map(${valueAlias} => ${childrenCode})`\n}\n\n/**\n * 生成 render 函数\n */\nfunction genRenderFunction(\n\tview: ViewBlock,\n\tctx: ModuleCodegenContext\n): void {\n\tctx.code += 'function render() {\\n'\n\tctx.code += '\\treturn '\n\n\tif (view.children.length === 0) {\n\t\tctx.code += 'null'\n\t} else if (view.children.length === 1) {\n\t\tctx.code += genChildNode(view.children[0], ctx, 1)\n\t} else {\n\t\tconst childrenCode = view.children\n\t\t\t.map(child => genChildNode(child, ctx, 1))\n\t\t\t.join(',\\n\\t\\t')\n\t\tctx.code += `[\\n\\t\\t${childrenCode}\\n\\t]`\n\t}\n\n\tctx.code += '\\n}\\n'\n}\n\n// ==================== Style 代码生成 ====================\n\n/**\n * 生成 style 块\n * 将 CSS 内容注入到文档中\n */\nfunction genStyleBlock(\n\tstyle: StyleBlock,\n\tctx: ModuleCodegenContext\n): void {\n\tif (!style.content.trim()) {\n\t\treturn\n\t}\n\n\t// 生成一个唯一的 style ID(基于内容 hash)\n\tconst styleId = `style_${Buffer.from(style.content).toString('base64').slice(0, 8)}`\n\n\t// 生成注入样式表的代码\n\tctx.code += `\\n// 注入样式\\n`\n\tctx.code += `;(function() {\\n`\n\tctx.code += `\\tif (typeof document !== 'undefined') {\\n`\n\tctx.code += `\\t\\tconst style = document.getElementById('${styleId}')\\n`\n\tctx.code += `\\t\\tif (!style) {\\n`\n\tctx.code += `\\t\\t\\tconst el = document.createElement('style')\\n`\n\tctx.code += `\\t\\t\\tel.id = '${styleId}'\\n`\n\tctx.code += `\\t\\t\\tel.textContent = \\`${style.content.replace(/`/g, '\\\\`').replace(/\\$/g, '\\\\$')}\\`\\n`\n\tctx.code += `\\t\\t\\tdocument.head.appendChild(el)\\n`\n\tctx.code += `\\t\\t}\\n`\n\tctx.code += `\\t}\\n`\n\tctx.code += `})()\\n`\n}\n\n// ==================== 主入口 ====================\n\n/**\n * 生成模块代码\n */\nexport function generateModule(\n\tast: NuiRootNode\n): NuiCompileResult {\n\tconst ctx = createModuleCodegenContext()\n\tconst errors = [...ast.imports, ...ast.signals, ...ast.functions]\n\t\t.map(() => null)\n\t\t.filter(Boolean) || []\n\n\t// 1. 生成用户 import 语句\n\tfor (const imp of ast.imports) {\n\t\tgenImportDeclaration(imp, ctx)\n\t}\n\n\t// 空行\n\tif (ast.imports.length > 0) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 2. 生成运行时 import 语句\n\tgenRuntimeImports(ast.signals, ast.functions, ast.view, ctx)\n\n\t// 空行\n\tif (ast.signals.length > 0 || ast.functions.length > 0 || ast.view) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 3. 生成 signal 声明\n\tfor (const signal of ast.signals) {\n\t\tgenSignalDeclaration(signal, ctx)\n\t}\n\n\t// 空行\n\tif (ast.signals.length > 0 && ast.functions.length > 0) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 4. 生成 function 定义\n\tfor (const fn of ast.functions) {\n\t\tgenFunctionDeclaration(fn, ctx)\n\t}\n\n\t// 空行\n\tif (ast.functions.length > 0 && ast.view) {\n\t\tctx.code += '\\n'\n\t}\n\n\t// 5. 生成 render 函数\n\tif (ast.view) {\n\t\tgenRenderFunction(ast.view, ctx)\n\t}\n\n\t// 6. 生成 style 块\n\tif (ast.style) {\n\t\tgenStyleBlock(ast.style, ctx)\n\t}\n\n\t// 7. 生成默认导出(组件对象)\n\tif (ast.view) {\n\t\tctx.code += '\\nexport default { render }\\n'\n\t}\n\n\t// 创建模板 AST(用于后续处理)\n\tconst templateAst: RootNode | null = ast.view\n\t\t? createRoot(ast.view.children)\n\t\t: null\n\n\treturn {\n\t\tcode: ctx.code,\n\t\tast,\n\t\ttemplateAst,\n\t\terrors: []\n\t}\n}","/**\n * compiler-nui\n * NUI DSL 编译器\n */\n\n// 导出枚举和值\nexport {\n\t// Token 类型\n\tTokenType,\n\n\t// NUI AST 节点类型\n\tNuiNodeTypes,\n\n\t// 错误代码\n\tNuiErrorCodes,\n\n\t// 工具\n\tKEYWORDS\n} from './types'\n\n// 导出类型(使用 type 关键字)\nexport type {\n\t// Token\n\tToken,\n\n\t// NUI AST 节点\n\tNuiRootNode,\n\tImportDeclaration,\n\tSignalDeclaration,\n\tFunctionDeclaration,\n\tViewBlock,\n\tStyleBlock,\n\n\t// 解析选项\n\tNuiParseOptions,\n\tNuiParseResult,\n\tNuiCompileResult,\n\n\t// 错误\n\tNuiCompilerError,\n\n\t// 状态\n\tTokenizerState,\n\tParserState\n} from './types'\n\n// 导出词法分析器\nexport { tokenize, readUntilNewline, initTokenizerState } from './tokenizer'\n\n// 导出解析器\nexport {\n\tparseStatements,\n\tparseImportDeclaration,\n\tparseSignalDeclaration,\n\tparseFunctionDeclaration,\n\tparseViewBlock\n} from './parser'\n\n// 导出类型\nexport type { StatementParseResult } from './parser'\n\n// 导出代码生成器\nexport { generateModule } from './codegen'\n\n// ==================== 编译入口 ====================\n\nimport {\n\tNuiRootNode,\n\tNuiParseOptions,\n\tNuiParseResult,\n\tNuiCompileResult,\n\tNuiNodeTypes,\n\tViewBlock,\n\tStyleBlock,\n\tToken,\n\tTokenType,\n\tNuiCompilerError\n} from './types'\nimport { tokenize } from './tokenizer'\nimport { parseStatements, parseViewBlock } from './parser'\nimport { generateModule } from './codegen'\nimport { createSourceLocation, Position } from '@fluxion-ui/compiler-core'\n\n/**\n * 解析 NUI 源码为 AST\n */\nexport function parse(source: string, options: NuiParseOptions = {}): NuiParseResult {\n\t// 1. 词法分析\n\tconst { tokens, errors: tokenErrors } = tokenize(source)\n\n\tif (options.onError) {\n\t\tfor (const error of tokenErrors) {\n\t\t\toptions.onError(error)\n\t\t}\n\t}\n\n\t// 2. 解析语句\n\tconst statementResult = parseStatements(tokens)\n\n\t// 3. 解析 view 块\n\tconst viewResult = parseViewBlock(tokens)\n\n\t// 4. 解析 style 块\n\tconst styleResult = parseStyleBlock(source, tokens)\n\n\t// 5. 构建 AST\n\tconst ast: NuiRootNode = {\n\t\ttype: NuiNodeTypes.NUI_ROOT,\n\t\timports: statementResult.imports,\n\t\tsignals: statementResult.signals,\n\t\tfunctions: statementResult.functions,\n\t\tview: viewResult.view,\n\t\tstyle: styleResult.style,\n\t\tloc: createSourceLocation(\n\t\t\t{ offset: 0, line: 1, column: 1 } as Position,\n\t\t\t{ offset: source.length, line: 1, column: 1 } as Position,\n\t\t\tsource\n\t\t),\n\t\tsource\n\t}\n\n\t// 收集所有错误\n\tconst errors = [\n\t\t...tokenErrors,\n\t\t...statementResult.errors,\n\t\t...viewResult.errors,\n\t\t...styleResult.errors\n\t]\n\n\treturn { ast, errors }\n}\n\n/**\n * 解析 style 块\n * 从源码中提取 style 块的内容\n */\nfunction parseStyleBlock(source: string, tokens: Token[]): {\n\tstyle: StyleBlock | null\n\terrors: NuiCompilerError[]\n} {\n\t// 找到 STYLE token\n\tlet styleToken: Token | null = null\n\tfor (const token of tokens) {\n\t\tif (token.type === TokenType.STYLE) {\n\t\t\tstyleToken = token\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (!styleToken) {\n\t\treturn { style: null, errors: [] }\n\t}\n\n\t// 从 style 关键字后面开始,找到缩进后的内容\n\t// style 关键字的位置\n\tconst styleStart = styleToken.loc.start.offset\n\n\t// 找到 style 后的换行符\n\tlet contentStart = styleStart + 5 // 'style'.length\n\twhile (contentStart < source.length && source[contentStart] !== '\\n') {\n\t\tcontentStart++\n\t}\n\tcontentStart++ // 跳过换行\n\n\t// 跳过缩进(第一个 tab)\n\tif (contentStart < source.length && source[contentStart] === '\\t') {\n\t\tcontentStart++\n\t}\n\n\t// 提取 style 内容直到文件末尾\n\t// 需要处理缩进:移除每行开头的 tab\n\tlet content = ''\n\tlet i = contentStart\n\tlet lineStart = true\n\n\twhile (i < source.length) {\n\t\tconst char = source[i]\n\n\t\tif (char === '\\n') {\n\t\t\tcontent += char\n\t\t\ti++\n\t\t\tlineStart = true\n\t\t} else if (lineStart && char === '\\t') {\n\t\t\t// 跳过行首的 tab(缩进)\n\t\t\ti++\n\t\t\tlineStart = false\n\t\t} else {\n\t\t\tcontent += char\n\t\t\ti++\n\t\t\tlineStart = false\n\t\t}\n\t}\n\n\t// 创建 style 块\n\tconst styleBlock: StyleBlock = {\n\t\ttype: NuiNodeTypes.STYLE_BLOCK,\n\t\tcontent: content.trim(),\n\t\tloc: styleToken.loc\n\t}\n\n\treturn { style: styleBlock, errors: [] }\n}\n\n/**\n * 编译 NUI 源码为 JavaScript 代码\n */\nexport function compile(source: string, options: NuiParseOptions = {}): NuiCompileResult {\n\t// 解析\n\tconst { ast, errors } = parse(source, options)\n\n\t// 代码生成\n\tconst result = generateModule(ast)\n\n\treturn {\n\t\t...result,\n\t\terrors: [...errors, ...result.errors]\n\t}\n}"],"names":["TokenType","NuiNodeTypes","NuiErrorCodes","KEYWORDS","import","from","function","if","elif","else","for","in","view","style","signal","asyncSignal","NEWLINE","createPosition","offset","line","column","createSourceLocation","start","end","source","createError","code","message","loc","error","SyntaxError","createToken","type","value","initTokenizerState","indentStack","tokens","errors","currentChar","state","length","peekChar","n","advance","char","skipWhitespace","countIndent","indent","handleIndent","currentIndent","topIndent","push","INDENT","pop","DEDENT","INCONSISTENT_INDENT","readString","startLoc","quote","INVALID_STRING","escaped","endLoc","STRING","readNumber","startOffset","startLine","startColumn","hasDecimal","next","NUMBER","isUnicodeLetter","test","readIdentifier","keywordType","IDENTIFIER","readUntilNewline","content","tokenize","atLineStart","indentTokens","AT","EQUALS","COMMA","LPAREN","RPAREN","LBRACE","RBRACE","DOT","OPERATOR","UNEXPECTED_TOKEN","EOF","initParserState","index","currentToken","indentLevel","isTokenType","expectToken","errorMessage","token","skipNewlines","skipIndent","parseImportDeclaration","startToken","IMPORT","identifierToken","identifier","FROM","sourceToken","IMPORT_DECLARATION","parseSignalDeclaration","name","isAsync","ASYNC_SIGNAL","SIGNAL","initExpression","SIGNAL_DECLARATION","parseFunctionDeclaration","FUNCTION","nameToken","params","parseFunctionParams","body","braceDepth","trim","parseFunctionBody","FUNCTION_DECLARATION","parseStatements","imports","signals","functions","decl","isValidElementTag","isNativeTag","readExpression","expr","parenDepth","savedIndex","parseElement","tagName","props","atToken","INVALID_VIEW_SYNTAX","eventName","handler","createDirectiveNode","attrName","firstToken","isStaticValue","attrValue","valueToken","attr","createAttributeNode","isStatic","parseElementProps","createElementNode","parseIfStatement","IF","branches","condition","ifChildren","parseChildren","createIfBranchNode","createSimpleExpression","ELIF","elifCondition","elifChildren","ELSE","elseChildren","createIfNode","parseForStatement","FOR","valueAlias","IN","FOR_WITHOUT_IN","children","createForNode","parseInlineContent","nodes","currentText","currentTextLoc","flushText","createTextNode","createInterpolationNode","ifNode","forNode","textContent","textLoc","t","element","inlineChildren","tag","textNodes","elementChildren","ELIF_WITHOUT_IF","ELSE_WITHOUT_IF","parseViewBlock","foundView","VIEW","VIEW_BLOCK","genImportDeclaration","ctx","genSignalDeclaration","genFunctionDeclaration","join","genElementNode","node","isComponent","args","propsObj","prop","NodeTypes","ATTRIBUTE","DIRECTIVE","arg","exp","handlerName","charAt","toUpperCase","slice","genPropsObject","every","child","TEXT","combinedText","map","childCode","genChildNode","childrenParts","i","ELEMENT","text","includes","parts","lastIndex","regex","match","exec","genTextWithInterpolation","INTERPOLATION","exprContent","branch","convertSignalAccess","consequent","genBranchChildren","genIfNode","childrenCode","genForNode","result","replace","ident","generateModule","ast","filter","Boolean","imp","Set","add","some","s","size","Array","genRuntimeImports","fn","genRenderFunction","styleId","Buffer","toString","genStyleBlock","templateAst","createRoot","parse","options","tokenErrors","onError","statementResult","viewResult","styleResult","styleToken","STYLE","contentStart","lineStart","STYLE_BLOCK","parseStyleBlock","NUI_ROOT","compile"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@fluxion-ui/compiler-nui",
3
+ "version": "0.0.3",
4
+ "description": "Fluxion compiler for NUI DSL - .nui file parser and compiler",
5
+ "type": "module",
6
+ "main": "./dist/compiler-nui.cjs",
7
+ "module": "./dist/compiler-nui.js",
8
+ "types": "./dist/compiler-nui.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/compiler-nui.js",
12
+ "require": "./dist/compiler-nui.cjs",
13
+ "types": "./dist/compiler-nui.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/AiFu-o/fluxion"
22
+ },
23
+ "keywords": [
24
+ "fluxion",
25
+ "compiler",
26
+ "nui",
27
+ "dsl"
28
+ ],
29
+ "author": "Fluxion Team",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@fluxion-ui/compiler-core": "0.0.3",
33
+ "@fluxion-ui/shared": "0.0.3",
34
+ "@fluxion-ui/compiler-dom": "0.0.3"
35
+ }
36
+ }