Archived
333 lines
20 KiB
HTML
333 lines
20 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Namespace Hi.NcParsers.EvaluationSyntaxs.Heidenhain | HiAPI-C# 2025 </title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="title" content="Namespace Hi.NcParsers.EvaluationSyntaxs.Heidenhain | HiAPI-C# 2025 ">
|
||
|
||
|
||
<link rel="icon" href="../img/HiAPI.favicon.ico">
|
||
<link rel="stylesheet" href="../public/docfx.min.css">
|
||
<link rel="stylesheet" href="../public/main.css">
|
||
<meta name="docfx:navrel" content="../toc.html">
|
||
<meta name="docfx:tocrel" content="toc.html">
|
||
|
||
<meta name="docfx:rel" content="../">
|
||
|
||
|
||
|
||
<meta name="loc:inThisArticle" content="In this article">
|
||
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||
<meta name="loc:tocFilter" content="Filter by title">
|
||
<meta name="loc:nextArticle" content="Next">
|
||
<meta name="loc:prevArticle" content="Previous">
|
||
<meta name="loc:themeLight" content="Light">
|
||
<meta name="loc:themeDark" content="Dark">
|
||
<meta name="loc:themeAuto" content="Auto">
|
||
<meta name="loc:changeTheme" content="Change theme">
|
||
<meta name="loc:copy" content="Copy">
|
||
<meta name="loc:downloadPdf" content="Download PDF">
|
||
|
||
<script type="module" src="./../public/docfx.min.js"></script>
|
||
|
||
<script>
|
||
const theme = localStorage.getItem('theme') || 'auto'
|
||
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
||
</script>
|
||
|
||
</head>
|
||
|
||
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
|
||
<header class="bg-body border-bottom">
|
||
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
||
<div class="container-xxl flex-nowrap">
|
||
<a class="navbar-brand" href="../index.html">
|
||
<img id="logo" class="svg" src="../img/HiAPI.logo.png" alt="">
|
||
|
||
</a>
|
||
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
||
<i class="bi bi-three-dots"></i>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navpanel">
|
||
<div id="navbar">
|
||
<form class="search" role="search" id="search">
|
||
<i class="bi bi-search"></i>
|
||
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
|
||
<main class="container-xxl">
|
||
<div class="toc-offcanvas">
|
||
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
||
<div class="offcanvas-header">
|
||
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
||
</div>
|
||
<div class="offcanvas-body">
|
||
<nav class="toc" id="toc"></nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<div class="actionbar">
|
||
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
||
<i class="bi bi-list"></i>
|
||
</button>
|
||
|
||
<nav id="breadcrumb"></nav>
|
||
</div>
|
||
|
||
<article data-uid="Hi.NcParsers.EvaluationSyntaxs.Heidenhain">
|
||
|
||
<h1 id="Hi_NcParsers_EvaluationSyntaxs_Heidenhain" data-uid="Hi.NcParsers.EvaluationSyntaxs.Heidenhain" class="text-break">Namespace Hi.NcParsers.EvaluationSyntaxs.Heidenhain</h1>
|
||
<div class="markdown level0 summary"></div>
|
||
<div class="markdown level0 conceptual"></div>
|
||
<div class="markdown level0 remarks"></div>
|
||
|
||
<h3 id="classes">
|
||
Classes
|
||
</h3>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainExpressionParser.html">HeidenhainExpressionParser</a></dt>
|
||
<dd><p>Recursive-descent parser for Heidenhain klartext FN value expressions.
|
||
Produces the same <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.NcExpr.html">NcExpr</a> AST as the Fanuc
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.NcExpressionParser.html">NcExpressionParser</a> so <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.NcExpressionEvaluator.html">NcExpressionEvaluator</a>
|
||
is reused unchanged. Pure: no variable lookup, no evaluation.</p>
|
||
<p>Grammar (lowest precedence at top):</p>
|
||
<pre><code class="lang-csharp">expr := add-expr
|
||
add-expr := term (('+' | '-') term)*
|
||
term := factor (('*' | '/' | 'DIV') factor)*
|
||
factor := ('+' | '-')? primary
|
||
primary := number
|
||
| '(' expr ')'
|
||
| 'Q' digits | 'QR' digits | 'QL' digits | 'QS' digits
|
||
| func primary → prefix form "SQRT 4" (FN 5)
|
||
| func '(' arglist ')' → paren form "SQRT(Q2)"</code></pre>
|
||
<p>
|
||
Dialect notes: Q-family tokens are canonicalised to uppercase
|
||
(<code>q1</code> → <code>Q1</code>) so <code>Parsing.Assignments</code> keys, table
|
||
lookups and same-block references agree. (Caveat shared with the
|
||
Siemens R canonicalisation: a lowercase-captured Assignments key
|
||
keeps its raw spelling in the evaluator's same-block dictionary, so
|
||
a later same-block reference resolves to the pre-block value instead
|
||
— klartext posts emit uppercase, corpus-zero.) <code>DIV</code> is the FN 4
|
||
division spelling (<code>FN 4: Q4 = +8 DIV +Q2</code>) and maps onto the
|
||
shared divide operator. Function names are limited to the klartext
|
||
math vocabulary (<code>SQRT SIN COS TAN ASIN ACOS ATAN ABS INT FRAC SGN
|
||
NEG LN LOG EXP</code>); <code>INT</code> normalises to the evaluator's
|
||
<code>FIX</code> (truncate toward zero), names the shared evaluator lacks
|
||
(<code>FRAC</code>/<code>SGN</code>/<code>NEG</code>/<code>LOG</code>) parse fine and fail
|
||
soft at evaluation. Any other identifier is a parse error — klartext
|
||
has no named variables, and rejecting bare words keeps the
|
||
evaluator's Parsing-tree pass from touching non-expression strings
|
||
(<code>MM</code>, <code>MAX</code>, tool-axis letters). Comparison/logical
|
||
operators are deliberately absent: FN 9–12 jump conditions are
|
||
pre-normalised by
|
||
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainGotoParsingSyntax.html">HeidenhainGotoParsingSyntax</a>
|
||
into separate value operands plus a shared comparison word — never
|
||
parsed here.
|
||
</p>
|
||
</dd>
|
||
</dl>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainGotoSyntax.html">HeidenhainGotoSyntax</a></dt>
|
||
<dd><p>Resolves Heidenhain FN 9–12 conditional jumps — the
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucGotoSyntax.html">FanucGotoSyntax</a> pattern with klartext <code>LBL</code>
|
||
targets and a structural condition. Triggered by
|
||
<code>Parsing.HeidenhainGoto</code> (written by
|
||
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainGotoParsingSyntax.html">HeidenhainGotoParsingSyntax</a>); decides whether to fire,
|
||
and on fire calls
|
||
<a class="xref" href="Hi.Common.Collections.LazyLinkedList-1.html#Hi_Common_Collections_LazyLinkedList_1_ReplaceSource_System_Collections_Generic_IEnumerable__0__">ReplaceSource(IEnumerable<T>)</a> on
|
||
<code>layers[0]</code> with the re-segmented file content starting at the
|
||
target label line (inclusive — the definition marker is consumed by
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramReturnSyntax.html">HeidenhainSubProgramReturnSyntax</a> downstream).</p>
|
||
<p>
|
||
The condition is compared here, not by the expression grammar: the
|
||
parsing owner pre-normalised the statement into two value operands
|
||
plus a shared comparison word (the P2 decision that keeps the
|
||
Heidenhain dialect free of comparison/logical layers). Each operand is
|
||
read polymorphically — numeric (typed at capture for literals, or
|
||
substituted in place by <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> for
|
||
resolved Q references) fires the comparison; a still-string operand
|
||
means unresolved (the FN 18 SYSREAD target staying vacant is the
|
||
designed source) and the jump warns
|
||
<code>HeidenhainGoto--ConditionNotEvaluated</code> and falls through — no
|
||
fabricated values, both endings stay fail-soft.
|
||
</p>
|
||
<p>
|
||
The label scan is whole-file first-match through the runner's own
|
||
segmenter (<a class="xref" href="Hi.NcParsers.Dependencys.SystemWired.SegmenterDependency.html">SegmenterDependency</a>) with the P4 call-path
|
||
probe stack — klartext has no direction mnemonic and a TNC label is
|
||
unique per program, so the anchored directional overloads would add a
|
||
distinction the language does not have. Numeric labels canonicalize
|
||
(<code>"01"</code> ≡ <code>1</code>); <code>GOTO LBL 0</code> targets the
|
||
end-of-subprogram sentinel and is refused
|
||
(<code>HeidenhainGoto--Lbl0Target</code>, the
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html">HeidenhainSubProgramCallSyntax</a> precedent). Jumps hosted
|
||
inside a P4 inlined body (<code>CALL LBL</code>/<code>CALL PGM</code> splice or a
|
||
<code>REP</code> section pass) are recognized but not simulated — the
|
||
redirect would discard the pending inline tail
|
||
(<code>HeidenhainGoto--InlinedContextUnsupported</code>, the Siemens P5
|
||
guard).
|
||
</p>
|
||
<p>
|
||
Pipeline placement: tail of the Heidenhain Evaluation bundle, after
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> (operand substitution) and the Q
|
||
reader. The <a class="xref" href="Hi.NcParsers.Dependencys.Heidenhain.HeidenhainGotoIterationDependency.html">HeidenhainGotoIterationDependency</a> watchdog
|
||
caps fired jumps per <code>(file, label)</code>; a missing watchdog disables
|
||
the cap (Fanuc parity).
|
||
</p>
|
||
</dd>
|
||
</dl>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainQParameterReadingSyntax.html">HeidenhainQParameterReadingSyntax</a></dt>
|
||
<dd><p>Obtains values for Heidenhain Q parameters by consuming literal numeric
|
||
assignments from <code>Parsing.Assignments.Qn</code>/<code>QRn</code> and routing
|
||
them by id range — one reader for the single <code>Q</code> key shape, range
|
||
routing inside (the Heidenhain analogue of the Fanuc range-routed reader
|
||
trio):</p>
|
||
<ul><li><code>Q0-Q99</code> → <a class="xref" href="Hi.NcParsers.Dependencys.Heidenhain.HeidenhainQParameterTable.html">HeidenhainQParameterTable</a> free range
|
||
(hincproj-persisted; the table is the single source of truth — no JSON
|
||
mirror).</li><li><code>QRn</code> → the same table's permanent QR store.</li><li><code>Q100-Q199</code> → controller-written system parameters: the write
|
||
is consumed but not applied, with a
|
||
<code>HeidenhainQ--SystemReadOnly</code> warning (no fabricated values).</li><li><code>Q200+</code> → volatile range: dict-merged into
|
||
<code>Vars.Volatile</code> with canonical <code>Q</code>+id keys, carried
|
||
block-to-block like the Fanuc <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VolatileVariableReadingSyntax.html">VolatileVariableReadingSyntax</a>;
|
||
cleared at program end by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndCleanSyntax.html">ProgramEndCleanSyntax</a>.</li></ul>
|
||
<p>
|
||
The carry of the previous block's <code>Vars.Volatile</code> happens on every
|
||
block regardless of assignments, so the single-step traceback contract of
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainVolatileQLookup.html">HeidenhainVolatileQLookup</a> holds.
|
||
</p>
|
||
<p>
|
||
Only literal numeric RHS values are consumed
|
||
(<code>Q1 = 5000</code> ✓; <code>Q1 = Q1*.75</code> ✗). Non-literal RHS entries are
|
||
left untouched in <code>Parsing.Assignments</code>;
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> resolves them to literals earlier
|
||
on the same block, so by the time this syntax runs, every evaluable RHS
|
||
is literal. The two syntaxes are decoupled.
|
||
</p>
|
||
</dd>
|
||
</dl>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html">HeidenhainSubProgramCallSyntax</a></dt>
|
||
<dd><p>Consumes the <code>Parsing.CALL</code> record captured by
|
||
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainCallSyntax.html">HeidenhainCallSyntax</a> and executes the three klartext
|
||
call mechanisms over the shared M98 inline machinery:</p>
|
||
<ul><li><b><code>CALL LBL n</code> / <code>CALL LBL "name"</code></b> (subprogram):
|
||
the host file is re-segmented through the runner's own segmenter
|
||
(<a class="xref" href="Hi.NcParsers.Dependencys.SystemWired.SegmenterDependency.html">SegmenterDependency</a>), scanned for the matching
|
||
<code>LBL</code> definition with <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a> and the
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_LabelProbeSyntaxes">LabelProbeSyntaxes</a>, truncated at the first following
|
||
<code>LBL 0</code> (inclusive — its consumption pops the frame), and
|
||
prepended into <code>layers[0]</code> with a pushed <a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a>
|
||
frame. A subprogram without <code>LBL 0</code> is a structured safe-skip
|
||
(inlining to EOF would double-execute the file tail).</li><li><b><code>CALL LBL n REP m</code></b> (program-section repeat — TNC
|
||
semantics: the section from <code>LBL n</code> up to, not including, the
|
||
call line runs m extra times): m fresh re-segmentation passes of that
|
||
slice are prepended. A loop, not a call — no new <a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a>
|
||
frame is pushed, but the host block's stack propagates onto the
|
||
repeated pieces so nested calls inside the section still accumulate
|
||
depth against the rail; the repeat count itself is a literal bound.
|
||
Any <code>LBL 0</code> passed inside the section is a no-op for the return
|
||
syntax (null-safe pop).</li><li><b><code>CALL PGM name</code></b>: resolved through
|
||
<a class="xref" href="Hi.NcParsers.Dependencys.Generic.SubProgramFolderConfig.html#Hi_NcParsers_Dependencys_Generic_SubProgramFolderConfig_InternalFolder">InternalFolder</a> with the
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_FilePatterns">FilePatterns</a> chain (<code>{0}.h</code> → <code>{0}.H</code> →
|
||
<code>{0}</code>) and inlined whole — the
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramCallSyntax.html">SiemensSubProgramCallSyntax</a> mechanism verbatim,
|
||
including resolve-miss safe-skip
|
||
(<code>HeidenhainCall--Skipped</code>). The callee's <code>END PGM</code> pops
|
||
the frame via
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramReturnSyntax.html">HeidenhainSubProgramReturnSyntax</a>; a unit switch inside
|
||
the callee is not restored on return (recorded limitation).</li></ul>
|
||
<p>
|
||
Recursion rail: like the Siemens call path, a self-recursive
|
||
<code>CALL LBL</code>/<code>CALL PGM</code> would splice forever; a call whose
|
||
host block already carries <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_MaxCallDepth">MaxCallDepth</a>
|
||
<a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a> frames is consumed as a safe-skip with
|
||
<code>HeidenhainCall--DepthLimitExceeded</code>. No <a class="xref" href="Hi.NcParsers.Keywords.MacroFrame.html">MacroFrame</a>
|
||
is stamped — klartext subprograms share the caller's Q scope.
|
||
</p>
|
||
Pipeline placement: head of the Heidenhain <code>Evaluation</code> bundle
|
||
(the Fanuc discipline — call/inline ahead of all variable machinery).
|
||
</dd>
|
||
</dl>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramReturnSyntax.html">HeidenhainSubProgramReturnSyntax</a></dt>
|
||
<dd><p>Consumes the two klartext return spellings and the standalone label
|
||
markers:</p>
|
||
<ul><li><b><code>LBL 0</code></b> — end-of-subprogram sentinel: stamps
|
||
<a class="xref" href="Hi.NcParsers.Keywords.SubProgramReturn.html">SubProgramReturn</a> (<code>Term: "LBL 0"</code>) and pops the
|
||
<a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a> frame (null-safe: an <code>LBL 0</code> reached in
|
||
the main flow — the 1.H head layout — is a no-op). Like the Fanuc
|
||
M99, the "return" itself is structural: the call syntax truncated the
|
||
inlined slice at this block, so the caller's tail follows
|
||
naturally.</li><li><b><code>LBL n</code> / <code>LBL "name"</code></b> — definition markers:
|
||
consumed into a block-root <a class="xref" href="Hi.NcParsers.Keywords.Heidenhain.HeidenhainLbl.html">HeidenhainLbl</a> record (no
|
||
motion; keeps the label visible for dumps and the P5 jump
|
||
family).</li><li><b><code>END PGM</code> with a non-empty <a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a></b> —
|
||
the return of a <code>CALL PGM</code> callee: consumes <code>Parsing.PGM</code>
|
||
before the Logic program-header syntax can treat it as a real program
|
||
end (which would clear the volatile Q store mid-stream), stamps
|
||
<a class="xref" href="Hi.NcParsers.Keywords.SubProgramReturn.html">SubProgramReturn</a> (<code>Term: "END PGM"</code>), and pops the
|
||
frame. The main file's <code>END PGM</code> (empty stack) is untouched.</li></ul>
|
||
Pipeline placement: directly after
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html">HeidenhainSubProgramCallSyntax</a> at the head of the
|
||
Evaluation bundle.
|
||
</dd>
|
||
</dl>
|
||
<dl class="jumplist">
|
||
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainVolatileQLookup.html">HeidenhainVolatileQLookup</a></dt>
|
||
<dd><p>Reads Heidenhain volatile Q parameters (<code>Q200+</code>, the cycle/user
|
||
range that resets at program start) from <code>Vars.Volatile</code>. Self-gates
|
||
the id range so the evaluator's
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html#Hi_NcParsers_EvaluationSyntaxs_VariableEvaluatorSyntax_RuntimeVariableLookups">RuntimeVariableLookups</a> chain can
|
||
fall through for other keys (<code>Q0-Q99</code>/<code>QRn</code> resolve on the
|
||
<a class="xref" href="Hi.NcParsers.Dependencys.Heidenhain.HeidenhainQParameterTable.html">HeidenhainQParameterTable</a> further
|
||
down the chain; <code>Q100-Q199</code> stay vacant by design). Sibling of the
|
||
Fanuc <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.VolatileVariableLookup.html">VolatileVariableLookup</a> with the same
|
||
single-step traceback contract:
|
||
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainQParameterReadingSyntax.html">HeidenhainQParameterReadingSyntax</a> dict-merges every block's
|
||
<code>Vars.Volatile</code> into the next block, so the entry — if it exists —
|
||
is on the current block or the immediately previous one.</p>
|
||
<p>
|
||
Keys are stored canonically as <code>Q</code> + id by the reader; this lookup
|
||
re-canonicalises the incoming key the same way, so lowercase raw
|
||
captures still resolve. Stateless and dependency-free.
|
||
</p>
|
||
</dd>
|
||
</dl>
|
||
|
||
|
||
</article>
|
||
|
||
<div class="contribution d-print-none">
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<div class="affix">
|
||
<nav id="affix"></nav>
|
||
</div>
|
||
</main>
|
||
|
||
<div class="container-xxl search-results" id="search-results"></div>
|
||
|
||
<footer class="border-top text-secondary">
|
||
<div class="container-xxl">
|
||
<div class="flex-fill">
|
||
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</body>
|
||
</html>
|