fix SoftNcRunner GM code normalization.

This commit is contained in:
2026-05-06 13:21:19 +08:00
parent 0fe9497552
commit 2f57932000
1238 changed files with 69405 additions and 22511 deletions
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class SoftNcUtil | HiAPI-C# 2025 ">
<meta name="description" content="JSON helpers for soft-NC blocks: vectors under , motion-term queries, flag grab/remove on raw text, and unparsed-line trimming.">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
@@ -97,7 +97,9 @@ Class SoftNcUtil
<dl><dt>Assembly</dt><dd>HiMech.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown summary"><p>JSON helpers for soft-NC blocks: vectors under <a class="xref" href="Hi.NcParsers.Keywords.IParsingDef.html#Hi_NcParsers_Keywords_IParsingDef_Parsing">Parsing</a>,
motion-term queries, flag grab/remove on raw text, and unparsed-line trimming.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
@@ -191,19 +193,133 @@ non-word-character prefixes (e.g. Fanuc '#', Siemens '$').</p>
</h2>
<a id="Hi_NcParsers_SoftNcUtil_GetOccupiedMotionMode_" data-uid="Hi.NcParsers.SoftNcUtil.GetOccupiedMotionMode*"></a>
<a id="Hi_NcParsers_SoftNcUtil_GetMachineStateDouble_" data-uid="Hi.NcParsers.SoftNcUtil.GetMachineStateDouble*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetOccupiedMotionMode_System_Text_Json_Nodes_JsonObject_" data-uid="Hi.NcParsers.SoftNcUtil.GetOccupiedMotionMode(System.Text.Json.Nodes.JsonObject)">
GetOccupiedMotionMode(JsonObject)
<h3 id="Hi_NcParsers_SoftNcUtil_GetMachineStateDouble_System_Text_Json_Nodes_JsonObject_System_String_" data-uid="Hi.NcParsers.SoftNcUtil.GetMachineStateDouble(System.Text.Json.Nodes.JsonObject,System.String)">
GetMachineStateDouble(JsonObject, string)
</h3>
<div class="markdown level1 summary"><p>Removes empty sub-nodes from Parsing, then removes Parsing itself if empty.</p>
<div class="markdown level1 summary"><p>Reads a numeric tag from a <b>machine-state</b> section (one written by
a LogicSyntax / Semantic with explicit numeric values, not from the
parser stage). Used by backward-walk lookback paths
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html">ProgramXyzUtil</a> FindPrevious*,
<code>FindPreviousState</code> on Feedrate/SpindleSpeed/IsoLocalCoordinateOffset,
modal arc-/linear-feedrate prev-block reads, etc.) where the data is
supposed to be guaranteed numeric and any non-numeric is a HiAPIs
codegen bug rather than an unevaluated user expression.</p>
<ul><li>Tag missing → returns <code>null</code> silently (the section may not
have been written on a previous block; caller's <code>?? default</code>
chain handles it).</li><li>Tag present and numeric → returns the value.</li><li>Tag present but non-numeric → throws
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.invalidoperationexception">InvalidOperationException</a> immediately. The
stack trace anchors the bug at the read site (which is the right
place to investigate — the originating block has already passed).
Continuing with NaN/0 would silently propagate corrupt coordinates
downstream and is more dangerous than crashing the run.</li></ul>
Use <a class="xref" href="Hi.NcParsers.SoftNcUtil.html#Hi_NcParsers_SoftNcUtil_GetParsedDouble_System_Text_Json_Nodes_JsonObject_System_String_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_">GetParsedDouble(JsonObject, string, Sentence, NcDiagnosticProgress)</a> instead when reading from a parser-
stage section (variable expressions on the current block deserve a
soft diagnostic, not a hard crash).
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static string GetOccupiedMotionMode(this JsonObject json)</code></pre>
<pre><code class="lang-csharp hljs">public static double? GetMachineStateDouble(this JsonObject section, string key)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>section</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">JsonObject</a></dt>
<dd></dd>
<dt><code>key</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double">double</a>?</dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_SoftNcUtil_GetMachineStateVec3d_" data-uid="Hi.NcParsers.SoftNcUtil.GetMachineStateVec3d*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetMachineStateVec3d_System_Text_Json_Nodes_JsonObject_System_String_" data-uid="Hi.NcParsers.SoftNcUtil.GetMachineStateVec3d(System.Text.Json.Nodes.JsonObject,System.String)">
GetMachineStateVec3d(JsonObject, string)
</h3>
<div class="markdown level1 summary"><p><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> reader for <b>machine-state</b> sections (written
by upstream LogicSyntaxes / Semantics with explicit numeric values).
Section missing → returns <code>null</code>; individual missing X/Y/Z
components fall through to <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double.nan">NaN</a>; a non-numeric
value at any of X/Y/Z throws via
<a class="xref" href="Hi.NcParsers.SoftNcUtil.html#Hi_NcParsers_SoftNcUtil_GetMachineStateDouble_System_Text_Json_Nodes_JsonObject_System_String_">GetMachineStateDouble(JsonObject, string)</a> — non-numeric here is a HiAPIs
codegen bug, not a user-facing unevaluated expression, and silently
degrading to NaN/0 would propagate corrupt coordinates downstream.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d GetMachineStateVec3d(JsonObject json, string sectionKey)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>json</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">JsonObject</a></dt>
<dd></dd>
<dt><code>sectionKey</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_SoftNcUtil_GetOccupiedMotionEventForm_" data-uid="Hi.NcParsers.SoftNcUtil.GetOccupiedMotionEventForm*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetOccupiedMotionEventForm_System_Text_Json_Nodes_JsonObject_" data-uid="Hi.NcParsers.SoftNcUtil.GetOccupiedMotionEventForm(System.Text.Json.Nodes.JsonObject)">
GetOccupiedMotionEventForm(JsonObject)
</h3>
<div class="markdown level1 summary"><p>Reads the form on the current block's <a class="xref" href="Hi.NcParsers.Keywords.MotionEvent.html">MotionEvent</a>
section, indicating that a motion event has already been authored on
this block by an earlier-stage motion syntax. Returns null when no
motion event is present on this block. Used by motion syntaxes to
enforce mutual exclusion (only one motion event per block).</p>
<p>
Reads <a class="xref" href="Hi.NcParsers.Keywords.MotionEvent.html">MotionEvent</a> rather than
<a class="xref" href="Hi.NcParsers.Keywords.MotionState.html">MotionState</a> because state is modally carried
onto every block via <a class="xref" href="Hi.NcParsers.PostLogicSyntaxs.ModalCarrySyntax.html">ModalCarrySyntax</a> and
would always appear "occupied"; only the event section is sparse
and meaningfully indicates an authored claim on this block.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static string GetOccupiedMotionEventForm(this JsonObject json)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -228,20 +344,93 @@ non-word-character prefixes (e.g. Fanuc '#', Siemens '$').</p>
<a id="Hi_NcParsers_SoftNcUtil_GetVec3d_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d*"></a>
<a id="Hi_NcParsers_SoftNcUtil_GetParsedDouble_" data-uid="Hi.NcParsers.SoftNcUtil.GetParsedDouble*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetVec3d_System_Text_Json_Nodes_JsonObject_System_String_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d(System.Text.Json.Nodes.JsonObject,System.String)">
GetVec3d(JsonObject, string)
<h3 id="Hi_NcParsers_SoftNcUtil_GetParsedDouble_System_Text_Json_Nodes_JsonObject_System_String_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_" data-uid="Hi.NcParsers.SoftNcUtil.GetParsedDouble(System.Text.Json.Nodes.JsonObject,System.String,Hi.NcParsers.Sentence,Hi.NcParsers.NcDiagnosticProgress)">
GetParsedDouble(JsonObject, string, Sentence, NcDiagnosticProgress)
</h3>
<div class="markdown level1 summary"><p>Read <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> from a sub-object with X/Y/Z keys.
Returns null if the section or all three keys are missing.</p>
<div class="markdown level1 summary"><p>Reads a numeric tag from a JSON object held on a <a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>
(the <a class="xref" href="Hi.NcParsers.Keywords.IParsingDef.html#Hi_NcParsers_Keywords_IParsingDef_Parsing">Parsing</a> tree, a previously-written modal
section, or any sub-object thereof), with strict separation between
&ldquo;tag absent&rdquo; and &ldquo;tag present but not a number&rdquo;.</p>
<ul><li>Tag missing → returns <code>null</code> silently. The caller's existing
<code>?? default</code> chain handles the "axis not written" /
"section absent" case as before.</li><li>Tag present and numeric → returns the value.</li><li>Tag present but non-numeric → emits
<a class="xref" href="Hi.NcParsers.NcDiagnosticProgress.html#Hi_NcParsers_NcDiagnosticProgress_UnsupportedError_Hi_NcParsers_Sentence_System_String_System_String_System_Object_">UnsupportedError(Sentence, string, string, object)</a>
(id <code>VariableExpression--Unevaluated</code>) and returns <code>null</code>.
Two sources land here:
<ul><li>Parser-stage residue — a Fanuc <code>"#124"</code>, Heidenhain
<code>"Q1"</code>, Siemens <code>"R5"</code>, or bracket expression
<code>"[#100+5]"</code> stored as a string by
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.FloatTagValueSyntax.html#Hi_NcParsers_ParsingSyntaxs_FloatTagValueSyntax_ToFloat_System_String_">ToFloat(string)</a> /
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.IntegerTagValueSyntax.html#Hi_NcParsers_ParsingSyntaxs_IntegerTagValueSyntax_ToInteger_System_String_">ToInteger(string)</a>
when the literal parse failed. Remediation: wire up the
variable evaluator.</li><li>Codegen residue — a previously-written modal section that
somehow ended up with a non-numeric JsonValue. Remediation: file
a HiAPIs bug. Severity is intentionally the same; reconfigurable
diagnostic routing handles operator-vs-developer triage and a
second error id would be cosmetic.</li></ul>
</li></ul>
Replaces the legacy idiom <code>section[key]?.GetDouble()</code> at every
call site that consumes a numeric tag held on a <a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>.
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d GetVec3d(JsonObject json, string sectionKey)</code></pre>
<pre><code class="lang-csharp hljs">public static double? GetParsedDouble(this JsonObject section, string key, Sentence sentence, NcDiagnosticProgress diag)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>section</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">JsonObject</a></dt>
<dd></dd>
<dt><code>key</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>sentence</code> <a class="xref" href="Hi.NcParsers.Sentence.html">Sentence</a></dt>
<dd></dd>
<dt><code>diag</code> <a class="xref" href="Hi.NcParsers.NcDiagnosticProgress.html">NcDiagnosticProgress</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double">double</a>?</dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_SoftNcUtil_GetVec3d_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetVec3d_System_Text_Json_Nodes_JsonObject_System_String_Hi_Geom_Vec3d_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d(System.Text.Json.Nodes.JsonObject,System.String,Hi.Geom.Vec3d,Hi.NcParsers.Sentence,Hi.NcParsers.NcDiagnosticProgress)">
GetVec3d(JsonObject, string, Vec3d, Sentence, NcDiagnosticProgress)
</h3>
<div class="markdown level1 summary"><p>Reads <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> from a sub-object with X/Y/Z keys,
substituting each missing component (or a missing section) with
the matching component of <code class="paramref">fallback</code>.</p>
<p>
When <code class="paramref">sentence</code> is non-null and <code class="paramref">diag</code>
is supplied, non-numeric X/Y/Z values are reported via
<a class="xref" href="Hi.NcParsers.SoftNcUtil.html#Hi_NcParsers_SoftNcUtil_GetParsedDouble_System_Text_Json_Nodes_JsonObject_System_String_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_">GetParsedDouble(JsonObject, string, Sentence, NcDiagnosticProgress)</a>; when <code class="paramref">sentence</code> is
null, the diagnostic still fires but without a source-line anchor.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d GetVec3d(JsonObject json, string sectionKey, Vec3d fallback, Sentence sentence, NcDiagnosticProgress diag)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -250,6 +439,65 @@ Returns null if the section or all three keys are missing.</p>
<dd></dd>
<dt><code>sectionKey</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>fallback</code> <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
<dt><code>sentence</code> <a class="xref" href="Hi.NcParsers.Sentence.html">Sentence</a></dt>
<dd></dd>
<dt><code>diag</code> <a class="xref" href="Hi.NcParsers.NcDiagnosticProgress.html">NcDiagnosticProgress</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_SoftNcUtil_GetVec3d_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d*"></a>
<h3 id="Hi_NcParsers_SoftNcUtil_GetVec3d_System_Text_Json_Nodes_JsonObject_System_String_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_" data-uid="Hi.NcParsers.SoftNcUtil.GetVec3d(System.Text.Json.Nodes.JsonObject,System.String,Hi.NcParsers.Sentence,Hi.NcParsers.NcDiagnosticProgress)">
GetVec3d(JsonObject, string, Sentence, NcDiagnosticProgress)
</h3>
<div class="markdown level1 summary"><p>Read <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> from a sub-object with X/Y/Z keys.
Returns null if the section or all three keys are missing;
individual missing keys are filled with <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double.nan">NaN</a>.</p>
<p>
When <code class="paramref">sentence</code> is non-null and <code class="paramref">diag</code>
is supplied, non-numeric X/Y/Z values are reported via
<a class="xref" href="Hi.NcParsers.SoftNcUtil.html#Hi_NcParsers_SoftNcUtil_GetParsedDouble_System_Text_Json_Nodes_JsonObject_System_String_Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_">GetParsedDouble(JsonObject, string, Sentence, NcDiagnosticProgress)</a> (id <code>VariableExpression--Unevaluated</code>);
when <code class="paramref">sentence</code> is null, the diagnostic still fires
but without a source-line anchor (used by backward-walk / dump-reading
callers that cannot tie the read to the current sentence).
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d GetVec3d(JsonObject json, string sectionKey, Sentence sentence, NcDiagnosticProgress diag)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>json</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">JsonObject</a></dt>
<dd></dd>
<dt><code>sectionKey</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>sentence</code> <a class="xref" href="Hi.NcParsers.Sentence.html">Sentence</a></dt>
<dd></dd>
<dt><code>diag</code> <a class="xref" href="Hi.NcParsers.NcDiagnosticProgress.html">NcDiagnosticProgress</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
@@ -364,7 +612,8 @@ The text is changed by replacing tag and value to empty string.</p>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 summary"><p>Removes the first occurrence of any flag in <code class="paramref">tags</code> from <code class="paramref">text</code> (alternation regex).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
@@ -382,7 +631,8 @@ The text is changed by replacing tag and value to empty string.</p>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
<dd><p><code>true</code> if a match was removed.</p>
</dd>
</dl>
@@ -402,7 +652,8 @@ The text is changed by replacing tag and value to empty string.</p>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 summary"><p>True if <code class="paramref">text</code> contains any flag in <code class="paramref">flags</code> as whole tokens.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
@@ -440,7 +691,8 @@ The text is changed by replacing tag and value to empty string.</p>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 summary"><p>True if <code class="paramref">text</code> contains <code class="paramref">flag</code> as a whole token (see <a class="xref" href="Hi.NcParsers.SoftNcUtil.html#Hi_NcParsers_SoftNcUtil_RegexFlagPrefix">RegexFlagPrefix</a>).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
@@ -592,7 +844,8 @@ Returns 0 if null or unparseable.</p>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 summary"><p>Normalises <a class="xref" href="Hi.NcParsers.Keywords.IUnparsedTextDef.html#Hi_NcParsers_Keywords_IUnparsedTextDef_UnparsedText">UnparsedText</a> (trim, drop blank-only lines) and removes the property when empty.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
@@ -602,9 +855,11 @@ Returns 0 if null or unparseable.</p>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>root</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">JsonObject</a></dt>
<dd></dd>
<dd><p>Block JSON object.</p>
</dd>
<dt><code>unparsedText</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dd><p>Raw tail text after structured fields were consumed.</p>
</dd>
</dl>
@@ -625,7 +880,17 @@ Returns 0 if null or unparseable.</p>
</h3>
<div class="markdown level1 summary"><p>Write <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> to a sub-object with X/Y/Z keys.</p>
<div class="markdown level1 summary"><p>Writes <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a> to a sub-object under <code class="paramref">sectionKey</code>,
setting only the X/Y/Z keys. If the section already exists, other
keys (e.g. A/B/C on a shared <code>MachineCoordinate</code>) are
preserved; if it does not exist, a new sub-object is created.</p>
<p>
Upsert rather than replace so callers that write XYZ and ABC in
separate stages (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McXyzSyntax.html">McXyzSyntax</a> and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a>) can cooperate on the same
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a> section
without clobbering each other.
</p>
</div>
<div class="markdown level1 conceptual"></div>