Table of Contents

Class SiemensExpressionParser

Namespace
Hi.NcParsers.EvaluationSyntaxs.Siemens
Assembly
HiMech.dll

Recursive-descent parser for Sinumerik value expressions. Produces the same NcExpr AST as the Fanuc NcExpressionParser so NcExpressionEvaluator is reused unchanged. Pure: no variable lookup, no evaluation.

Grammar (lowest precedence at top):

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)*

Dialect differences from the Fanuc parser: parentheses group and call (Fanuc uses brackets); comparisons are spelled == <> >= <= > < (Fanuc uses EQ NE .. words); bare identifiers are named-variable references (Fanuc rejects an identifier without [); R63 is canonicalised to uppercase so table lookups and Parsing.Assignments keys agree. Indexed accesses ($P_UIFR[1,X,TR], _RENC[35]) require literal index elements (integers, bare letters, or keywords like TR) and are emitted as a single NcVariableExpr whose key is the canonical uppercase-indexed token — the whole token routes through Get(string), keeping the AST brand-agnostic. Function-name aliases are normalised where Sinumerik and the shared evaluator spell the same math differently: ATAN2ATAN (both are two-arg atan2 in degrees), TRUNCFIX (truncate toward zero). Unknown functions (e.g. the rotary positioning form DC(...)) parse fine and fail later in the evaluator, which callers treat as fail-soft.

public sealed class SiemensExpressionParser
Inheritance
SiemensExpressionParser
Inherited Members
Extension Methods

Methods

TryParse(string, out NcExpr, out string)

Parses source requiring the whole string to be consumed. On success, expr is the AST and error is null. On failure, expr is null and error describes the syntax problem.

public static bool TryParse(string source, out NcExpr expr, out string error)

Parameters

source string
expr NcExpr
error string

Returns

bool

TryParsePrefix(string, out NcExpr, out int, out string)

Parses the longest valid expression prefix of source. On success, consumedLength is the number of leading characters that form the expression (trailing text from that offset on is the caller's to keep, e.g. as remaining UnparsedText). Fails only when not even a prefix parses (e.g. the text starts with a quote or an operator dangles at end-of-input) — callers fall back to their legacy lexical capture in that case.

This is the parser-delimited RHS boundary: the expression grammar itself decides where the right-hand side ends, so whitespace inside expressions (R64 - 14/2), balanced call parentheses (DC(47.296)) and a following non-expression word (R24=14 R26=... / F=R103 X-204.) all resolve without lexical boundary regexes or TerminateWords.

public static bool TryParsePrefix(string source, out NcExpr expr, out int consumedLength, out string error)

Parameters

source string
expr NcExpr
consumedLength int
error string

Returns

bool