Archived
623 lines
40 KiB
HTML
623 lines
40 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Namespace Hi.NcParsers.EvaluationSyntaxs.Siemens | HiAPI-C# 2025 </title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="title" content="Namespace Hi.NcParsers.EvaluationSyntaxs.Siemens | 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.Siemens">
|
|
|
|
<h1 id="Hi_NcParsers_EvaluationSyntaxs_Siemens" data-uid="Hi.NcParsers.EvaluationSyntaxs.Siemens" class="text-break">Namespace Hi.NcParsers.EvaluationSyntaxs.Siemens</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.Siemens.SiemensAcIcSyntax.html">SiemensAcIcSyntax</a></dt>
|
|
<dd><p>Recognizes the Siemens per-word coordinate function family on axis
|
|
words — <code>AC(...)</code> (absolute), <code>IC(...)</code> (incremental),
|
|
<code>DC(...)</code> (rotary shortest-path), <code>ACP(...)</code> /
|
|
<code>ACN(...)</code> (rotary directional approach), and the coded-position
|
|
(indexing axis) counterparts <code>CAC(...)</code> / <code>CIC(...)</code> /
|
|
<code>CDC(...)</code> / <code>CACP(...)</code> / <code>CACN(...)</code> — e.g.
|
|
<code>X=AC(400)</code>, <code>C=IC(360/17)</code>, <code>C=DC(47.296)</code>,
|
|
<code>B=CAC(2)</code> — unwraps the inner
|
|
expression so the downstream <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a>
|
|
resolves it through the normal Siemens expression machinery, and
|
|
records the per-word positioning override in a block-root
|
|
<a class="xref" href="Hi.NcParsers.Keywords.PositioningOverride.html">PositioningOverride</a> section keyed by word name
|
|
(<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Absolute">Absolute</a> /
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a> /
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Shortest">Shortest</a> /
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_PositiveOnly">PositiveOnly</a> /
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_NegativeOnly">NegativeOnly</a>, and the
|
|
<code>Coded*</code> values for the coded-position verbs).</p>
|
|
<p>
|
|
Siemens semantics: the wrapper forces the interpretation of that one
|
|
coordinate word for that one block, regardless of the modal G90/G91
|
|
state. The positional conversion itself stays with the same consumers
|
|
that honor the modal state —
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a> for linear axes and
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> for rotary axes (both treat
|
|
every non-Incremental override as an absolute write), while the
|
|
rotary shortest/directional resolution stays with the
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> tail-pass — this
|
|
syntax only normalizes the text and stamps the override; it never
|
|
reads machine position (the Evaluation stage is not the place for
|
|
position-state reads).
|
|
</p>
|
|
<p>
|
|
Scope: axis words (per <a class="xref" href="Hi.NcParsers.Dependencys.IMachineAxisConfig.html#Hi_NcParsers_Dependencys_IMachineAxisConfig_AxisNames">AxisNames</a>,
|
|
falling back to X/Y/Z/A/B/C) accept the full family, except that the
|
|
rotary-only verbs <code>DC</code>/<code>ACP</code>/<code>ACN</code> are unwrapped only
|
|
on rotary axes (per <a class="xref" href="Hi.NcParsers.Dependencys.IMachineAxisConfig.html#Hi_NcParsers_Dependencys_IMachineAxisConfig_IsRotaryAxis_System_String_">IsRotaryAxis(string)</a>,
|
|
falling back to A/B/C) — on a linear axis they are invalid Siemens
|
|
and are left untouched so they surface as unevaluated residue
|
|
instead of being silently mis-read. The interpolation parameters
|
|
I/J/K accept <code>AC</code>/<code>IC</code> only (Siemens circle centers are
|
|
incremental by default; <code>I=AC(...)</code> switches that one component
|
|
to an absolute center coordinate, consumed by
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensCircularMotionSyntax.html">SiemensCircularMotionSyntax</a>) —
|
|
the rotary verbs are meaningless there and are left untouched.
|
|
The coded-position verbs (their argument is a 1-based indexing
|
|
position <b>number</b>, not a coordinate) are unwrapped only on axes
|
|
that <a class="xref" href="Hi.NcParsers.Dependencys.IIndexingPositionConfig.html#Hi_NcParsers_Dependencys_IIndexingPositionConfig_IsIndexingAxis_System_String_">IsIndexingAxis(string)</a> reports as
|
|
usable indexing axes — <code>CDC</code>/<code>CACP</code>/<code>CACN</code>
|
|
additionally require the axis to be rotary. Everywhere else (a
|
|
non-indexing axis, no indexing config on the list, I/J/K) they stay
|
|
untouched, mirroring the Siemens alarm 17500 ("axis is not an
|
|
indexing axis") with loud unevaluated residue. The number→coordinate
|
|
lookup happens at the write stage
|
|
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> /
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a> via
|
|
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CodedPositionUtil.html">CodedPositionUtil</a>), not here — the
|
|
Evaluation stage neither reads machine position nor resolves tables.
|
|
Positioning-axis forms (<code>POS[C]=DC(...)</code> / <code>SPOS=</code>) never
|
|
reach the word path and are out of scope. Values whose parentheses
|
|
do not balance around the wrapper (e.g. <code>IC(1)+AC(2)</code>) are also
|
|
left untouched.
|
|
</p>
|
|
<p>
|
|
Must be placed in the Evaluation bundle <b>before</b>
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> (the unwrapped inner text is a
|
|
plain Siemens expression the evaluator numeric-ifies on the same
|
|
block). Inside REPEAT / subprogram splices each re-fed piece runs the
|
|
full bundle again, so the unwrap happens on every iteration.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensExpressionParser.html">SiemensExpressionParser</a></dt>
|
|
<dd><p>Recursive-descent parser for Sinumerik 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 := or-expr
|
|
or-expr := and-expr (('OR' | 'XOR') and-expr)*
|
|
and-expr := cmp-expr ('AND' cmp-expr)*
|
|
cmp-expr := add-expr (('==' | '<>' | '>=' | '<=' | '>' | '<') add-expr)*
|
|
add-expr := term (('+' | '-') term)*
|
|
term := factor (('*' | '/' | 'MOD') factor)*
|
|
factor := ('+' | '-')? primary
|
|
primary := number
|
|
| '(' expr ')'
|
|
| 'R' digits → variable "R63" (canonical uppercase)
|
|
| '$' name ('[' indexlist ']')? → variable "$P_UIFR[1,X,TR]" (canonical)
|
|
| name '(' arglist ')' → function call
|
|
| name '[' indexlist ']' → variable "_RENC[35]" (canonical)
|
|
| name → variable "_X_HOME" (case preserved)
|
|
indexlist := (integer | name) (',' (integer | name))*
|
|
arglist := expr (',' expr)*</code></pre>
|
|
<p>
|
|
Dialect differences from the Fanuc parser: parentheses group and call
|
|
(Fanuc uses brackets); comparisons are spelled <code>==</code> <code><></code>
|
|
<code>>=</code> <code><=</code> <code>></code> <code><</code> (Fanuc uses
|
|
<code>EQ NE ..</code> words); bare identifiers are named-variable references
|
|
(Fanuc rejects an identifier without <code>[</code>); <code>R63</code> is
|
|
canonicalised to uppercase so table lookups and
|
|
<code>Parsing.Assignments</code> keys agree. Indexed accesses
|
|
(<code>$P_UIFR[1,X,TR]</code>, <code>_RENC[35]</code>) require literal index
|
|
elements (integers, bare letters, or keywords like <code>TR</code>) and are
|
|
emitted as a single <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.NcVariableExpr.html">NcVariableExpr</a> whose key is the
|
|
canonical uppercase-indexed token — the whole token routes through
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.IVariableLookup.html#Hi_NcParsers_EvaluationSyntaxs_Evaluation_IVariableLookup_Get_System_String_">Get(string)</a>, keeping the AST brand-agnostic.
|
|
Function-name aliases are normalised where Sinumerik and the shared
|
|
evaluator spell the same math differently: <code>ATAN2</code> → <code>ATAN</code>
|
|
(both are two-arg atan2 in degrees), <code>TRUNC</code> → <code>FIX</code>
|
|
(truncate toward zero). Unknown functions (e.g. the rotary positioning
|
|
form <code>DC(...)</code>) parse fine and fail later in the evaluator, which
|
|
callers treat as fail-soft.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensGotoSyntax.html">SiemensGotoSyntax</a></dt>
|
|
<dd><p>Resolves Siemens <code>GOTOF</code>/<code>GOTOB</code> control flow — the
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucGotoSyntax.html">FanucGotoSyntax</a> pattern with named-label targets
|
|
and explicit direction. Triggered by <code>Parsing.SiemensGoto</code>
|
|
(written by <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensGotoParsingSyntax.html">SiemensGotoParsingSyntax</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 — a Siemens label may prefix code).</p>
|
|
<p>
|
|
Direction comes from the mnemonic and drives the anchored
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a> overload: <code>GOTOF</code> takes the first
|
|
match strictly below the host line, <code>GOTOB</code> the nearest match
|
|
strictly above it — never the whole-file first match, which would
|
|
silently mis-target duplicate label texts. Targets may be a named
|
|
label (<code>LBL1:</code> line, matched Ordinal-exact on the block-root
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensLabel.html">SiemensLabel</a> record) or an <code>N<num></code> block
|
|
number (matched on <a class="xref" href="Hi.NcParsers.Keywords.IndexNote.html#Hi_NcParsers_Keywords_IndexNote_Number">Number</a>).
|
|
</p>
|
|
<p>
|
|
The conditional forms (<code>IF <cond> GOTOF <label></code>)
|
|
lean on <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a>'s pass-2 tree walk;
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucConditionReader.html#Hi_NcParsers_EvaluationSyntaxs_Fanuc_FanucConditionReader_ReadCondition_System_Text_Json_Nodes_JsonNode_">ReadCondition(JsonNode)</a> (a dialect-neutral
|
|
numeric-JSON reader despite its home) reads the resolved node.
|
|
Truthy fires; zero falls through silently; unresolved warns
|
|
<code>SiemensGoto--ConditionNotEvaluated</code> and falls through. Because
|
|
the label field is an ordinary Parsing string, a label name that
|
|
collides with a set named variable may have been substituted to a
|
|
numeric by the evaluator — the original text is then recovered from
|
|
the <code>Formula.SiemensGoto.Label</code> mirror.
|
|
</p>
|
|
<p>
|
|
Pipeline placement: Evaluation bundle, in the control-flow group
|
|
after <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a>. The
|
|
<a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensGotoIterationDependency.html">SiemensGotoIterationDependency</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.Siemens.SiemensIfSyntax.html">SiemensIfSyntax</a></dt>
|
|
<dd><p>Resolves the Siemens <code>IF ... [ELSE ...] ENDIF</code> block
|
|
conditional. Three phrases dispatched by
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensIf.html#Hi_NcParsers_Keywords_Siemens_SiemensIf_Term">Term</a>, none of which needs a frame stack:</p>
|
|
<ul><li><code>IF</code> — reads the resolved condition via
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucConditionReader.html">FanucConditionReader</a> (dialect-neutral numeric-JSON
|
|
reader). True falls through into the then-branch; false
|
|
forward-jumps to just after the matching <code>ELSE</code> (else-branch
|
|
executes) or after the matching <code>ENDIF</code> when no else exists;
|
|
unresolved warns <code>SiemensIf--ConditionNotEvaluated</code> and falls
|
|
through (no redirect on unresolved input — the then-branch
|
|
executes, and the ELSE rule below then skips the else-branch,
|
|
which keeps the two branches mutually exclusive even on the
|
|
fail-soft path).</li><li><code>ELSE</code> — reached in the normal stream only when the
|
|
then-branch just executed (a false IF jumps past the ELSE line
|
|
directly), so it unconditionally forward-jumps past the matching
|
|
<code>ENDIF</code>.</li><li><code>ENDIF</code> — consumed no-op (stamped for cache dumps).</li></ul>
|
|
<p>
|
|
Both forward scans run on the anchored <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a>
|
|
overload from the host line, with a nesting-depth predicate: each
|
|
nested block-<code>IF</code> increments the depth, each <code>ENDIF</code> at
|
|
depth > 0 decrements it, and the match fires only at depth 0. The
|
|
probe stack replays the Parsing statement owners the depth counter
|
|
depends on — including <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensGotoParsingSyntax.html">SiemensGotoParsingSyntax</a> ahead
|
|
of <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensIfParsingSyntax.html">SiemensIfParsingSyntax</a>, so a nested single-line
|
|
<code>IF cond GOTOF lbl</code> is claimed by the GOTO owner and never
|
|
miscounted as a block-IF.
|
|
</p>
|
|
<p>
|
|
Pipeline placement: Evaluation bundle control-flow group, after
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> (condition substituted) and
|
|
before the variable readers.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensInlineContextUtil.html">SiemensInlineContextUtil</a></dt>
|
|
<dd><p>Detects whether a block executes inside a P4 inlined body — an
|
|
L/name-call subprogram splice or a <code>REPEAT label</code> section
|
|
repetition. Both are <code>PrependSource</code> inlines whose “return to
|
|
the caller / to the line after REPEAT” is the natural pipeline tail;
|
|
the P5 control-flow redirects (<code>ReplaceSource</code> with a
|
|
re-segmented host-file slice) would silently discard that pending
|
|
tail — and, for a section repeat, re-execute the <code>REPEAT</code>
|
|
statement itself, which has no watchdog (its count is eagerly known)
|
|
and therefore no bound. The P5 jump syntaxes consult this guard and
|
|
degrade to a structured warning + fall-through instead: control flow
|
|
inside an inlined body is recognized but not simulated (corpus count
|
|
zero; true support needs return-frame machinery, a future work
|
|
item).</p>
|
|
<ul><li>Subprogram context: the call syntax stamps a pushed
|
|
<a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a> on every inlined piece — any frame on the
|
|
stack marks callee context.</li><li>Section-repeat context: <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensRepeatSyntax.html">SiemensRepeatSyntax</a>
|
|
stamps every inlined piece with a <a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensRepeat.html">SiemensRepeat</a>
|
|
clone carrying a 1-based <a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensRepeat.html#Hi_NcParsers_Keywords_Siemens_SiemensRepeat_Iteration">Iteration</a>;
|
|
the REPEAT host block itself never carries that field.</li></ul>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensLoopSyntax.html">SiemensLoopSyntax</a></dt>
|
|
<dd><p>Resolves the four Siemens loop constructs against one shared frame
|
|
stack — <code>WHILE ... ENDWHILE</code>, <code>FOR ... ENDFOR</code>,
|
|
<code>REPEAT ... UNTIL</code> (the label-less post-test loop) and
|
|
<code>LOOP ... ENDLOOP</code> — the
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucWhileDoSyntax.html">FanucWhileDoSyntax</a> template (frames-in-JSON +
|
|
ModalCarry tracked key + forward scan to the terminator + back-jump
|
|
to the recorded entry line), adapted to constructs that carry no
|
|
LoopId: frames stack in nesting order on the block-root
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensLoopFrames.html">SiemensLoopFrames</a> section, and every terminator
|
|
validates that the innermost frame carries its own construct
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensLoopFrame.html#Hi_NcParsers_Keywords_Siemens_SiemensLoopFrame_Kind">Kind</a> and file. A single shared stack
|
|
is what makes mixed-construct nesting (a FOR inside a WHILE inside a
|
|
LOOP) pair correctly.</p>
|
|
<ul><li><b>WHILE</b> — pre-test: truthy pushes a frame (first
|
|
arrival) and falls through; falsy/unresolved pops its own frame
|
|
and forward-jumps past the matching <code>ENDWHILE</code>
|
|
(depth-counted). <code>ENDWHILE</code> back-jumps unconditionally; the
|
|
WHILE line re-evaluates.</li><li><b>FOR</b> — counting: first arrival resolves the bounds
|
|
once (Sinumerik semantics), assigns the loop variable by lifting
|
|
into <code>Parsing.Assignments</code> (the reader syntaxes downstream
|
|
persist it exactly as a written assignment), and pushes a frame
|
|
carrying <code>Var/End/Value</code>; each re-arrival increments
|
|
<code>Value</code> until it exceeds <code>End</code>, then pops and jumps past
|
|
<code>ENDFOR</code>.</li><li><b>REPEAT/UNTIL</b> — post-test: <code>REPEAT</code> pushes and
|
|
always falls through; <code>UNTIL</code> exits on truthy (pop), warns
|
|
and exits on unresolved, back-jumps to the <code>REPEAT</code> line on
|
|
falsy.</li><li><b>LOOP/ENDLOOP</b> — endless: <code>ENDLOOP</code> back-jumps
|
|
while the <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensLoopIterationDependency.html">SiemensLoopIterationDependency</a> watchdog
|
|
allows; the watchdog is a hard requirement here (no exit
|
|
condition exists), so a missing dependency suppresses the jump
|
|
with a configuration error instead of hanging the pipeline.</li></ul>
|
|
<p>
|
|
Back-jump counting happens at the back-jump step only (a loop whose
|
|
condition is false from the outset consumes zero iterations), keyed
|
|
<code>(FileName, BeginLineNo)</code> on the watchdog. All scans use the
|
|
anchored <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a> overload from the host line —
|
|
never the whole-file first match, which would pair a terminator with
|
|
an earlier sibling construct of the same kind.
|
|
</p>
|
|
<p>
|
|
Pipeline placement: Evaluation bundle control-flow group, after
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> (conditions and bounds
|
|
substituted) and before the variable readers (the FOR lift must
|
|
reach them on the same block).
|
|
</p>
|
|
<p>
|
|
<b>Known limitation — stack pairing vs lexical pairing.</b> Real
|
|
Sinumerik pairs loop constructs lexically at block preparation; this
|
|
syntax pairs them dynamically on the carried frame stack. A
|
|
<code>GOTOF</code>/<code>GOTOB</code> that leaves a loop body strands that
|
|
loop's frame (only the FOR head detects and drops a stale frame, via
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensLoopFrame.html#Hi_NcParsers_Keywords_Siemens_SiemensLoopFrame_AdvancePending">AdvancePending</a>), so a jump from an
|
|
inner loop into an <em>enclosing</em> loop's body can mispair the
|
|
enclosing terminator with the stale inner frame. Sinumerik itself
|
|
forbids jumping into control structures; all such shapes stay
|
|
bounded here by the watchdog and surface loud diagnostics. Scan
|
|
probes also mirror the Fanuc convention of not replaying
|
|
<code>BlockSkipSyntax</code> — a <code>/</code>-prefixed terminator is invisible
|
|
to the exit scans.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensNamedVariableLookup.html">SiemensNamedVariableLookup</a></dt>
|
|
<dd><p>Reads Sinumerik named program variables (<code>_X_HOME</code>) from
|
|
<code>Vars.Named</code>. Self-gates on the named-identifier key shape 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. Sibling of the Fanuc
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.VolatileVariableLookup.html">VolatileVariableLookup</a> with the same
|
|
single-step traceback: <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensNamedVariableReadingSyntax.html">SiemensNamedVariableReadingSyntax</a>
|
|
dict-merges every block's <code>Vars.Named</code> into the next block, so the
|
|
entry — if it exists — is on the current block or the immediately
|
|
previous one.</p>
|
|
<p>
|
|
Stateless and dependency-free — instances are interchangeable.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensNamedVariableReadingSyntax.html">SiemensNamedVariableReadingSyntax</a></dt>
|
|
<dd><p>Obtains values for Sinumerik named program variables (GUD/LUD
|
|
identifiers such as <code>_X_HOME</code>, declared via <code>DEF REAL</code> or
|
|
assigned directly). Reads literal numeric assignments from
|
|
<code>Parsing.Assignments.<ident></code>, dict-merges them with the
|
|
previous block's state, and writes the resulting per-block dictionary
|
|
into <code>Vars.Named</code> — the same carry-forward pattern as the Fanuc
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VolatileVariableReadingSyntax.html">VolatileVariableReadingSyntax</a>.</p>
|
|
<p>
|
|
Lifetime is bounded by <code>MachiningSession</code>: within one session the
|
|
dictionary carries forward block-by-block; session restart abandons the
|
|
SyntaxPiece JSON dataflow and starts fresh. This matches LUD scoping
|
|
well (program-local) and under-persists real GUD (globally retentive) —
|
|
acceptable until a GUD definition-file feature exists.
|
|
</p>
|
|
<p>
|
|
Only literal numeric RHS values are consumed
|
|
(<code>_X_HOME = 155.5</code> ✓; <code>_A = R1+5</code> ✗ — the evaluator resolves
|
|
those to literals earlier on the same block). String-valued RHS (quoted)
|
|
never reaches Assignments — the quote-guard syntaxes quarantine it in
|
|
the Parsing bundle.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensRParameterReadingSyntax.html">SiemensRParameterReadingSyntax</a></dt>
|
|
<dd><p>Obtains values for Sinumerik R parameters (<code>R0-R999</code>) by consuming
|
|
literal numeric assignments from <code>Parsing.Assignments.Rn</code> and
|
|
writing them straight to a registered <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensRParameterTable.html">SiemensRParameterTable</a>.
|
|
Sibling of the Fanuc <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.RetainedCommonVariableReadingSyntax.html">RetainedCommonVariableReadingSyntax</a>.</p>
|
|
<p>
|
|
No SyntaxPiece JSON mirror is created — the table is the single source of
|
|
truth for R values, and <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> reads from
|
|
the table directly (the table implements <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.IVariableLookup.html">IVariableLookup</a>).
|
|
The hincproj round-trip preserves writes across project sessions.
|
|
</p>
|
|
<p>
|
|
Only literal numeric RHS values are consumed by this syntax
|
|
(<code>R63 = 100.5</code> ✓; <code>R26 = R64-14/2</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>
|
|
<p>
|
|
If no <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensRParameterTable.html">SiemensRParameterTable</a> is registered on the runner's
|
|
effective <code>NcDependencyList</code>, this syntax is a no-op.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensRepeatSyntax.html">SiemensRepeatSyntax</a></dt>
|
|
<dd><p>Executes the Siemens <code>REPEAT StartLabel EndLabel [P=n]</code> section
|
|
repeat: the host file is re-segmented from the top, the
|
|
<code>[StartLabel: … EndLabel:)</code> slice is cut out (start-label line
|
|
included — it may carry trailing code; end-label line excluded), and
|
|
the slice is prepended into <code>layers[0]</code> once per repetition via
|
|
<a class="xref" href="Hi.Common.Collections.LazyLinkedList-1.html#Hi_Common_Collections_LazyLinkedList_1_PrependSource_System_Collections_Generic_IEnumerable__0__">PrependSource(IEnumerable<T>)</a>. “Return to the line
|
|
after REPEAT” is the natural pipeline tail — the M98-inline pattern —
|
|
so no return frame or rewind is needed (Siemens end labels are
|
|
passive, unlike Fanuc's <code>END m</code> which actively fires a syntax).</p>
|
|
<p>
|
|
Label scanning reuses <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a>'s predicate overload
|
|
with a Siemens probe stack (<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.CommentSyntaxs.TailCommentSyntax.html">TailCommentSyntax</a> +
|
|
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.HeadIndexSyntax.html">HeadIndexSyntax</a> + <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensLabelSyntax.html">SiemensLabelSyntax</a>) and
|
|
matches on the block-root <a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensLabel.html">SiemensLabel</a> record. Each
|
|
repetition is its own segmentation pass with a fresh fileIndex —
|
|
downstream syntaxes mutate block JSON in place, so repetitions must
|
|
not share piece instances. Every inlined block is stamped with a
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensRepeat.html">SiemensRepeat</a> clone carrying its 1-based
|
|
<a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensRepeat.html#Hi_NcParsers_Keywords_Siemens_SiemensRepeat_Iteration">Iteration</a>.
|
|
</p>
|
|
<p>
|
|
Fail-soft paths (consume + structured warning + no motion): missing
|
|
end label in the statement (single-label form — corpus count zero,
|
|
not simulated), start/end label not found in the file, a slice that
|
|
contains the REPEAT line itself (would re-fire forever — real
|
|
Sinumerik programs place REPEAT after the end label), and missing
|
|
runtime dependencies. The repetition count is known eagerly, so no
|
|
iteration watchdog is needed.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramCallSyntax.html">SiemensSubProgramCallSyntax</a></dt>
|
|
<dd><p>Consumes the <code>Parsing.SiemensCall</code> sub-object captured by
|
|
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensCallStatementSyntax.html">SiemensCallStatementSyntax</a> and
|
|
either inlines the called subprogram or safe-skips the call:</p>
|
|
<ul><li><b>Resolved</b> — the callee file (looked up 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.Siemens.SiemensSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Siemens_SiemensSubProgramCallSyntax_FilePatterns">FilePatterns</a> chain, default <code>{name}.SPF</code> →
|
|
<code>{name}.MPF</code> → <code>{name}</code>) is segmented and prepended into
|
|
<code>layers[0]</code> — the <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.SubProgramCallSyntax.html">SubProgramCallSyntax</a> (M98)
|
|
mechanism verbatim, including the <code>P</code>-times repetition loop,
|
|
per-repetition file indices, and a pushed <a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a>
|
|
frame that <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramReturnSyntax.html">SiemensSubProgramReturnSyntax</a> pops on
|
|
M17/RET. Like M98 (and unlike G65), no <a class="xref" href="Hi.NcParsers.Keywords.MacroFrame.html">MacroFrame</a> is
|
|
stamped — callee blocks share the caller's variable scope; DEF-local
|
|
isolation is a later work item.</li><li><b>Unresolved</b> — the corpus norm: OEM / measuring cycles
|
|
(<code>HQ_FC</code>, Renishaw <code>L9810</code>, <code>L_ZYM91</code>) whose
|
|
definition files ship with the machine, not the NC program. The call
|
|
is consumed whole with a block-root <a class="xref" href="Hi.NcParsers.Keywords.Siemens.SiemensCall.html">SiemensCall</a> record
|
|
(<code>Skipped: true</code>) and a single structured
|
|
<code>SiemensCall--Skipped</code> warning — motion state untouched,
|
|
replacing the raw <code>UnparsedText--Remaining</code> noise.</li></ul>
|
|
<p>
|
|
Pipeline placement: head of the Siemens <code>Evaluation</code> bundle
|
|
(the Fanuc discipline — call/inline ahead of all variable and motion
|
|
machinery). Argument binding to PROC parameters is not implemented:
|
|
a resolved call carrying arguments emits
|
|
<code>SiemensCall--ArgsNotBound</code> and inlines without bindings.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramReturnSyntax.html">SiemensSubProgramReturnSyntax</a></dt>
|
|
<dd><p>Consumes Siemens subprogram-end words — <code>M17</code> (subprogram end)
|
|
and <code>RET</code> (return without function output) — and pops one
|
|
<a class="xref" href="Hi.NcParsers.Keywords.CallStack.html">CallStack</a> frame. Like the plain-M99 half of
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.SubProgramReturnSyntax.html">SubProgramReturnSyntax</a>, the actual “return” is the
|
|
natural pipeline tail: the inlined body's last block is followed in
|
|
<code>layers[0]</code> by the caller's next block, so this syntax only
|
|
consumes the trigger (keeping
|
|
<a class="xref" href="Hi.NcParsers.InspectionSyntaxs.UnconsumedCheckSyntax.html">UnconsumedCheckSyntax</a> quiet), stamps a
|
|
<a class="xref" href="Hi.NcParsers.Keywords.SubProgramReturn.html">SubProgramReturn</a> section, and writes the popped stack.</p>
|
|
<p>
|
|
<code>M17</code> in the main frame (no caller) is the norm in practice —
|
|
post-processors commonly end a main <code>.MPF</code> with M17 — and is
|
|
consumed silently
|
|
with no pop and no warning, mirroring how a plain M99 tolerates the
|
|
main frame. Sinumerik's M17 has no <code>P</code>-jump form, so there is no
|
|
redirect path here.
|
|
</p>
|
|
<p>
|
|
Triggers: <code>M17</code> arrives in <code>Parsing.Flags</code> via
|
|
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.NumberedFlagSyntax.html">NumberedFlagSyntax</a>; <code>RET</code> via the
|
|
<a class="xref" href="Hi.NcParsers.Syntaxs.SiemensSyntaxUtil.html#Hi_NcParsers_Syntaxs_SiemensSyntaxUtil_FlagSyntax">FlagSyntax</a> word table.
|
|
</p>
|
|
<p>
|
|
<b>Known limitation — early return.</b> Because the return is the
|
|
natural pipeline tail, an <code>M17</code>/<code>RET</code> in the <em>middle</em>
|
|
of a body (e.g. inside an <code>IF</code> branch) pops the frame but does
|
|
not truncate the remaining inlined blocks — they still execute.
|
|
Honoring a mid-body return needs body-boundary bookkeeping (a future
|
|
work item alongside PROC parameter binding); the corpus places every
|
|
return at the body end.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSystemVariableSyntax.html">SiemensSystemVariableSyntax</a></dt>
|
|
<dd><p>Consumes writes to Sinumerik <code>$</code> system variables the pipeline does
|
|
not simulate (<code>$TC_DP…</code> handled elsewhere aside, e.g.
|
|
<code>$AC_TIME</code>, <code>$SC_…</code>, non-TR <code>$P_UIFR</code> components).
|
|
Siemens counterpart of the Fanuc record-only
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucSystemControlVariableSyntax.html">FanucSystemControlVariableSyntax</a> pattern:</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensUifrVariableLookup.html">SiemensUifrVariableLookup</a></dt>
|
|
<dd><p>Reads Sinumerik settable-frame translations
|
|
(<code>R100=$P_UIFR[1,X,TR]</code>) from the <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html">SiemensFrameTable</a>
|
|
on the runner's effective dependency list. Self-gates on the
|
|
<code>$P_UIFR[n,axis,TR]</code> key shape 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 (non-TR components fall to the record-only
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSystemVariableSyntax.html">SiemensSystemVariableSyntax</a> path as unevaluable reads).</p>
|
|
<p>
|
|
State-from-deps flavour: the table is resolved from the call's
|
|
<code>dependencies</code> list on every call — never held as a field —
|
|
so the lookup survives XML round-trip without a rebind path (the wrapper
|
|
anti-pattern ban on <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Evaluation.IRuntimeVariableLookup.html">IRuntimeVariableLookup</a>).
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl class="jumplist">
|
|
<dt><a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensUifrWritingSyntax.html">SiemensUifrWritingSyntax</a></dt>
|
|
<dd><p>Consumes Sinumerik settable-frame translation writes
|
|
(<code>$P_UIFR[5,Z,TR]=R102-281.48</code>, probing programs' workpiece
|
|
re-referencing idiom) by routing literal numeric assignments from
|
|
<code>Parsing.Assignments</code> into the <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html">SiemensFrameTable</a> on
|
|
the runner's effective dependency list — the write is thereby fully
|
|
simulated: a subsequent <code>G54/G505+</code> selection reads the updated
|
|
offset through the existing <code>CoordinateOffset</code> path (X/Y/Z), and
|
|
<code>$P_UIFR</code> reads see it via <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensUifrVariableLookup.html">SiemensUifrVariableLookup</a>.</p>
|
|
<p>
|
|
Only literal numeric RHS values are consumed;
|
|
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.VariableEvaluatorSyntax.html">VariableEvaluatorSyntax</a> normalizes expression RHS to
|
|
literals earlier on the same block. Only the <code>TR</code> component is
|
|
bridged — other components (<code>RT</code>, <code>FI</code>) stay in Assignments
|
|
and fall to the record-only <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSystemVariableSyntax.html">SiemensSystemVariableSyntax</a>,
|
|
which must run after this syntax. Writes to <code>$P_UIFR[0,..]</code>
|
|
(G500) are consumed but ignored, matching
|
|
<a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html#Hi_NcParsers_Dependencys_Siemens_SiemensFrameTable_SetAxisOffset_System_String_System_String_System_Double_">SetAxisOffset(string, string, double)</a>.
|
|
</p>
|
|
<p>
|
|
If no <a class="xref" href="Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html">SiemensFrameTable</a> is registered, this syntax is a
|
|
no-op (entries stay visible as unconsumed residue).
|
|
</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>
|