Table of Contents

Class CannedCycleResolveSyntax

Namespace
Hi.NcParsers.LogicSyntaxs
Assembly
HiMech.dll

Resolves the canned-cycle Group-09 state for the current block and writes the result to the CannedCycle section.

  • Active cycle (direct G81..G89 or modal repeat): merges Parsing overrides with previous-cycle stored params, applies G91 incremental-to-absolute conversion and missing-axis fallback, writes CannedCycle with Term, ReturnMode, and Params. The resolved cycle sub-section is left in Parsing under the cycle code for downstream cycle syntaxes (DrillingCycleSyntax, etc.) to read.
  • Explicit cancel (G80 flag present on a non-cycle block): consumes the G80 flag and writes CannedCycle = { Term: "G80" }, acting as a hard sentinel for Hi.NcParsers.LogicSyntaxs.CannedCycleSyntaxUtil modal lookback.
  • No Group-09 activity: leaves the block untouched.

A rotary-only block (C40.) reaches this syntax without a Parsing node — McAbcSyntax consumed the word into MachineCoordinateState and dropped the emptied node — but its one-shot RotaryWords record marks it as a block that spoke an axis word, so under an active cycle it is a modal repeat like any X/Y block (Fanuc's any-axis-word rule; HardNc indexes the table and drills again). The cycle's pre-positioning item then carries the block's ABC (WriteCompoundMotion(JsonObject, string, JsonArray, Vec3d)).

Must be placed after PositioningSyntax and before the individual cycle syntaxes in the chain.

public class CannedCycleResolveSyntax : ISituNcSyntax, INcSyntax, IMakeXmlSource
Inheritance
CannedCycleResolveSyntax
Implements
Inherited Members
Extension Methods

Examples

Direct G81 active cycle, no #Previous: (so lastProgramXyz = Vec3d.Zero) and no Positioning mode (so the absolute-coordinate path runs, not G91 incremental). The resolved cycle sub-section is left in Parsing under the cycle code for downstream cycle syntaxes to consume; the CannedCycle section carries the snapshot used for modal lookback. ReturnMode defaults to G98 when neither the current block nor a previous block declares G98/G99: #BeforeBuild:

{ "Parsing": { "G81": { "X": 50, "Y": 30, "Z": -10, "R": 2 } } }

#AfterBuild:

{
  "Parsing": { "G81": { "X": 50, "Y": 30, "Z": -10, "R": 2 } },
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  }
}

Modal repeat: the current block carries only an X override and no cycle code, but #Previous: has an active G81 with stored params. MergeModalCycleSection(JsonObject, JsonObject, ISentenceCarrier, NcDiagnosticProgress, out HashSet<string>) merges X=60 (override) with Y/Z/R from stored params, removes the consumed X from Parsing root, and writes the merged section back to Parsing.G81. ReturnMode inherits “G98” from the previous block's ReturnMode: #Previous:

{
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  },
  "ProgramXyz": { "X": 50, "Y": 30, "Z": 0 }
}

#BeforeBuild:

{ "Parsing": { "X": 60 } }

#AfterBuild:

{
  "Parsing": { "G81": { "X": 60, "Y": 30, "Z": -10, "R": 2 } },
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 60, "Y": 30, "Z": -10, "R": 2 }
  }
}

Explicit G80 cancel: standalone G80 flag with no cycle data. The G80 flag is consumed and CannedCycle = { Term: G80 } is written as a hard sentinel that FindPreviousActiveCycle(LazyLinkedListNode<SyntaxPiece>, string[]) reads to terminate modal lookback. No ReturnMode hint here (no G98/G99 flag on the same block): #BeforeBuild:

{ "Parsing": { "Flags": ["G80"] } }

#AfterBuild:

{ "CannedCycle": { "Term": "G80" } }

The first block after a program end — #Previous: carries the ProgramEnd section next to a still-active G81, and the block itself has an X word that would have repeated the cycle. This is the reset edge (ProgramEndSyntax): the controller's reset cancels the canned cycle, so no repeat is resolved (the X word stays for the positioning syntaxes) and the G80 sentinel is written explicitly — an authored section, so the modal carry does not clone the active cycle across the edge. No ReturnMode: the G98 default applies after reset: #Previous:

{
  "ProgramEnd": { "Term": "M30" },
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G99",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  }
}

#BeforeBuild:

{ "Parsing": { "X": 60 } }

#AfterBuild:

{
  "Parsing": { "X": 60 },
  "CannedCycle": { "Term": "G80" }
}

Rotary-only modal repeat: the block carries no Parsing at all (McAbcSyntax consumed C40. into MachineCoordinateState and dropped the emptied node) but its one-shot RotaryWords record says it spoke an axis word, so the active G81 from #Previous: repeats with every stored parameter (no override to merge). The Parsing node is re-created to host the resolved cycle sub-section for the downstream cycle syntax: #Previous:

{
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  },
  "ProgramXyz": { "X": 50, "Y": 30, "Z": 0 }
}

#BeforeBuild:

{
  "MachineCoordinateState": { "C": 40 },
  "RotaryWords": { "C": 40 }
}

#AfterBuild:

{
  "MachineCoordinateState": { "C": 40 },
  "RotaryWords": { "C": 40 },
  "Parsing": { "G81": { "X": 50, "Y": 30, "Z": -10, "R": 2 } },
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  }
}

Modal repeat under G91 (X10. pitch): only the block's own X word is an increment (50 + 10 = 60, from the previous block's machine position read back through this block's identity chain); the stored Y / Z / R are the previous cycle's absolute results and are reused verbatim instead of being added onto the anchors again (which would have moved Y to 60 and lifted Z to R + Z): #Previous:

{
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  },
  "ProgramXyz": { "X": 50, "Y": 30, "Z": 0 },
  "MachineCoordinateState": { "X": 50, "Y": 30, "Z": 0 }
}

#BeforeBuild:

{
  "Positioning": { "Term": "G91", "Mode": "Incremental" },
  "Parsing": { "X": 10 }
}

#AfterBuild:

{
  "Positioning": { "Term": "G91", "Mode": "Incremental" },
  "Parsing": { "G81": { "X": 60, "Y": 30, "Z": -10, "R": 2 } },
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 60, "Y": 30, "Z": -10, "R": 2 }
  }
}

A block whose Group-09 state a brand syntax already authored (the shape SiemensModalCycleSyntax writes for a bare MCALL cancel or an MCALL CYCLE8x(…) arm) is left alone even though #Previous: still carries an active G81 and the block spoke a rotary word: the authoring syntax owns the block, nothing repeats, and the sentinel survives for the blocks after it. (The Siemens parser only accepts MCALL alone on its block, so today this is the contract's guard rather than a reachable program line.) #Previous:

{
  "CannedCycle": {
    "Term": "G81",
    "ReturnMode": "G98",
    "Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
  },
  "ProgramXyz": { "X": 50, "Y": 30, "Z": 0 }
}

#BeforeBuild:

{
  "MachineCoordinateState": { "C": 40 },
  "RotaryWords": { "C": 40 },
  "CannedCycle": { "Term": "G80" }
}

#AfterBuild:

{
  "MachineCoordinateState": { "C": 40 },
  "RotaryWords": { "C": 40 },
  "CannedCycle": { "Term": "G80" }
}

Properties

Default

Default instance with standard settings.

public static CannedCycleResolveSyntax Default { get; }

Property Value

CannedCycleResolveSyntax

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