Table of Contents

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

src XElement

Source XML element.

Properties

Name

Syntax kind name (typically the concrete type name).

public string Name { get; }

Property Value

string

XName

XML element name used to register this syntax with XFactory.

public static string XName { get; }

Property Value

string

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

syntaxPieceNode LazyLinkedListNode<SyntaxPiece>
ncDependencyList List<INcDependency>
ncDiagnosticProgress NcDiagnosticProgress

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

baseDirectory string

The base directory for resolving relative paths

relFile string

The relative file path for the XML source

exhibitionOnly bool

if 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

factory XFactory