Class SiemensOrientationVectorSyntax
- Namespace
- Hi.NcParsers.ParsingSyntaxs.Siemens
- Assembly
- HiMech.dll
Captures the Siemens TRAORI orientation-programming words out of the
block text into the block-root SiemensOrientation record
and says, once per program, that they are recognized but not simulated
(Orientation-Vector–NotSimulated): the tool-axis vector
A3=/B3=/C3=, the Euler / RPY angles A2=/B2=/C2=
(ORIEULER / ORIRPY), the surface normals A4=/A5=, the cone and
intermediate-orientation vectors A6=…A8= — the whole
[ABC][2-8]= address family — and the ORI* interpolation
/ reference-system words (OrientationWords,
with a balanced parenthesized argument list such as
ORIRESET(0,0,0)). The rotary axes keep their previously
programmed positions.
Why a dedicated capture: NamedIdentPattern's
one-letter+digits alternative (there for H1=21) matches these
addresses too, and NamedVarAssignmentSyntax runs ahead of
the axis-word syntaxes — captured there, A3=0.5 became
Vars.Named.A3 without any diagnostic, the posture silently frozen
(the tool-vector plan's "partially eaten" hazard, found on the Siemens
preset 2026-09-29). This syntax therefore sits in the Parsing bundle
before NamedVarAssignmentSyntax, next to the
CR=/TURN= captures that exist for the same reason, and
after SiemensQuotedStatementSyntax so quoted text is never
shredded. H1=21 is outside the family and still lands in
Vars.Named.
Right-hand sides follow the assignment captures' rule: the lexical
boundary (the next word= or end of text) bounds the RHS, then the
Siemens expression grammar shrinks it to the longest valid prefix and
puts the tail back (C3=1 F1000 keeps F1000 for the feed
capture; glued A3=0B3=1 splits). A literal value is recorded as a
number, anything else verbatim as a string — the record sits outside
Parsing, so the variable evaluator does not rewrite it and the
unconsumed-Parsing check does not report it. An address written twice
on a block keeps its first value; the repeat goes to
Parsing.RepeatedWords (RepeatedWordsKey,
the pipeline's first-wins rule) and surfaces as
Parsing--Unconsumed.
The family is owned whole. A word of it that cannot be recorded is not
left for NamedVarAssignmentSyntax — there it would draw
the words after it into a failed right-hand side, or land in
Vars.Named — but set aside under
Parsing.SiemensOrientation, which nothing consumes: the
unconsumed check names it (Parsing--Unconsumed,
SiemensOrientation.A3) and its neighbours stay where they are.
That covers a right-hand side no prefix of which parses
(A3=1.2.3, A3=(R1+1; set aside up to the next blank) and
an address without a value, recognized by what follows the =:
nothing, another assignment (A3= B3=1), an NC address word
(A3= X10, A3= X-10.5 — one letter is never a Sinumerik
identifier, whose first two characters are letters or underscores;
R1 is the R parameter and is a value), or a bare word standing
apart from the = (A3= TRAFOOF). The last rule errs on the
visible side: a named variable written after a blank
(A3= MYVAR) is refused as well and shows up as residue, while
A3=MYVAR, A3= _MYVAR, A3= MYVAR*2 and
A3= SIN(30) are values. Not of the family, and left in the text:
an address or ORI* word that is the tail of an identifier or
follows $ (_P1A3=5 is the variable _P1A3; a glued
address chain G1X10A3=1 is not an identifier), and an
ORI* word whose parenthesis never closes.
Once per program: the notice is gated by a flag on this instance, set
when the notice fires and re-armed at a program boundary — the first
block of a stream (no block before it: a fresh session pipeline, also
on a runner reused across sessions), a TapeBoundary
block (a % line starts a new program) or a change of NC file (a
session may play several files in a row). The latter two are judged on
the program's own blocks only. Inlined pieces never count: the pieces
of a called subprogram (stamped SiemensCall and a pushed
CallStack by SiemensSubProgramCallSyntax
at splice time, the Sinumerik archive header %_N_L6_SPF a
callee file may start with included) and the pieces of a
REPEAT section
(IsInlinedContext(JsonObject); re-segmented
inside a callee they carry the callee's file and a clone of the host's
CallStack, propagated by SiemensRepeatSyntax,
but no SiemensCall record). A
program that calls such a subprogram a hundred times still gets one
notice. A program is told from the next by those three marks only:
the same file played again within one session and without a tape
boundary — or two inline plays under the same placeholder path — is
one program to this rule, and its notice is the one already among
the session's diagnostics. The syntax re-arms itself rather than through
ISessionResettable: the runner's session-reset sweep
covers the top-level syntax list, and this syntax sits inside the
Parsing BundleSyntax. A flag instead of a walk back
through the block list: frozen pieces re-parse their JSON on every
read, so a walk across a long three-axis section would have cost one
parse per block at the first vector block after it.
The plan's P4 reads Words to write the
brand-agnostic ToolOrientation / SurfaceNormal sections;
that step extends this class rather than adding a second one. A
project saved before this syntax existed carries its own serialized
syntax list without it (no legacy back-fill, by the policy stated on
SoftNcRunner.ApplyLegacyVersionPatches): it keeps the old
behaviour until its controller is set again from the Siemens preset.
public class SiemensOrientationVectorSyntax : ISituNcSyntax, INcSyntax, IMakeXmlSource
- Inheritance
-
SiemensOrientationVectorSyntax
- Implements
- Inherited Members
- Extension Methods
Examples
TRAORI vector block — the three words leave as a numeric record, the
motion words stay for the axis and feed captures:
#BeforeBuild.UnparsedText: G1 X10 Y0 Z0 A3=0 B3=0 C3=1 F1000
#AfterBuild:
{
"UnparsedText": "G1 X10 Y0 Z0 F1000",
"SiemensOrientation": { "Words": { "A3": 0, "B3": 0, "C3": 1 } }
}
Euler variant (A2= family) — same record, angles as written:
#BeforeBuild.UnparsedText: A2=30 B2=0 C2=0
#AfterBuild:
{
"SiemensOrientation": { "Words": { "A2": 30, "B2": 0, "C2": 0 } }
}
Non-literal right-hand side kept verbatim; the glued tail splits by
the expression grammar:
#BeforeBuild.UnparsedText: A3=R1 B3=0C3=1
#AfterBuild:
{
"SiemensOrientation": { "Words": { "A3": "R1", "B3": 0, "C3": 1 } }
}
ORI* words, the parenthesized ORIRESET form with its arguments:
#BeforeBuild.UnparsedText: ORIWKS ORIRESET(0,0,0) G1 X5
#AfterBuild:
{
"UnparsedText": "G1 X5",
"SiemensOrientation": { "Modes": ["ORIWKS", "ORIRESET(0,0,0)"] }
}
Not in the family — an underscore-led name, a two-digit address and
the arc radius stay for the syntaxes that own them:
#BeforeBuild.UnparsedText: _A3=1 A30=2 CR=5
#AfterBuild:
{
"UnparsedText": "_A3=1 A30=2 CR=5"
}
A right-hand side the grammar cannot parse — a malformed number, a
parenthesis left open — is set aside for the unconsumed check; the
axis word after it, the well-formed word next to it and the feed all
survive:
#BeforeBuild.UnparsedText: G1 A3=1.2.3 X10 B3=(R1+1 C3=1 F1000
#AfterBuild:
{
"UnparsedText": "G1 X10 F1000",
"Parsing": { "SiemensOrientation": { "A3": "1.2.3", "B3": "(R1+1" } },
"SiemensOrientation": { "Words": { "C3": 1 } }
}
A nested, spaced argument list is matched by parenthesis balance and
recorded in the one spelling WORD(args):
#BeforeBuild.UnparsedText: ORIRESET (SIN(30), 0, 0) G1 X5
#AfterBuild:
{
"UnparsedText": "G1 X5",
"SiemensOrientation": { "Modes": ["ORIRESET(SIN(30), 0, 0)"] }
}
An address without a value does not take what stands after it — a
signed axis word, a word of the block — and may end the text:
#BeforeBuild.UnparsedText: G1 A3= X-10.5 B3= TRAFOOF C3=
#AfterBuild:
{
"UnparsedText": "G1 X-10.5 TRAFOOF",
"Parsing": { "SiemensOrientation": { "A3": "", "B3": "", "C3": "" } }
}
Nor the assignment after it, which is captured in its own right:
#BeforeBuild.UnparsedText: A3= B3=1
#AfterBuild:
{
"Parsing": { "SiemensOrientation": { "A3": "" } },
"SiemensOrientation": { "Words": { "B3": 1 } }
}
The tail of an identifier and a name behind $ are not words of
the family, a glued address chain is:
#BeforeBuild.UnparsedText: _P1A3=5 $ORIWKS $A3=1 G1X10C3=1
#AfterBuild:
{
"UnparsedText": "_P1A3=5 $ORIWKS $A3=1 G1X10",
"SiemensOrientation": { "Words": { "C3": 1 } }
}
An address written twice keeps the first value; the repeat is listed
the pipeline's way:
#BeforeBuild.UnparsedText: A3=1 A3=2 B3=0
#AfterBuild:
{
"Parsing": { "RepeatedWords": { "A3": [2] } },
"SiemensOrientation": { "Words": { "A3": 1, "B3": 0 } }
}
An ORI* word whose parenthesis never closes is left whole:
#BeforeBuild.UnparsedText: ORIRESET(0,0 G1 X5
#AfterBuild:
{
"UnparsedText": "ORIRESET(0,0 G1 X5"
}
Constructors
SiemensOrientationVectorSyntax()
Initializes a new instance with default settings.
public SiemensOrientationVectorSyntax()
SiemensOrientationVectorSyntax(XElement)
Initializes a new instance by deserializing from the given XML element.
public SiemensOrientationVectorSyntax(XElement src)
Parameters
srcXElementSource XML element.
Properties
Name
Syntax kind name (typically the concrete type name).
public string Name { get; }
Property Value
XName
XML element name used to register this syntax with XFactory.
public static string XName { get; }
Property Value
Methods
Build(LazyLinkedListNode<SyntaxPiece>, List<INcDependency>, NcDiagnosticProgress)
Build syntax arrangement into the
syntaxPieceNode in-place.
public void Build(LazyLinkedListNode<SyntaxPiece> syntaxPieceNode, List<INcDependency> ncDependencyList, NcDiagnosticProgress ncDiagnosticProgress)
Parameters
syntaxPieceNodeLazyLinkedListNode<SyntaxPiece>ncDependencyListList<INcDependency>ncDiagnosticProgressNcDiagnosticProgress
MakeXmlSource(string, string, bool)
Creates an XML representation of the object. This method may also generate additional resources such as related files.
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
Parameters
baseDirectorystringThe base directory for resolving relative paths
relFilestringThe relative file path for the XML source
exhibitionOnlyboolif true, the extended file creation is suppressed.
Returns
- XElement
An XML element representing the object's state
Remarks
For the demand of easy moving source folder (especially project folder) without configuration file path corruption, the relative file path is applied.
The baseDirectory is typically the folder at the nearest configuration file folder.
Since the folder can be moving with the configuration file.
Reg(XFactory)
Registers this type's deserializer with the given XFactory
(or Default when factory is
null). Idempotent.
public static void Reg(XFactory factory = null)
Parameters
factoryXFactory