For making expressions in XCHEME you must use operators and operands, and there are three operator types: Unary, Binary and Ternary, let's take a look at how to work with them.
A unary operator requires a single operand always after the operator.
operator FOO
For example,
opt FOO
.
A binary operator requires two operands, one before and another one after the operator.
FOO operator BAR
For example,
FOO & BAR
orFOO and BAR
.
A ternary operator is a special operator that requires three operands, in XCHEME there's only one ternary operator that's used for conditionals.
FOO operator BAR operator BAZ
For example,
FOO then BAR else BAZ
.
The following table lists the precedence and associativity of all operators from top to bottom, in descending precedence order. Click on the name to know about the respective operator.
Precedence | Name | Associativity | Operator |
---|---|---|---|
1️⃣ | Grouping | N/A | (…) |
2️⃣ | Member access | Left to Right | … . … |
3️⃣ | Uncase | Right to Left | uncase … |
3️⃣ | Peek | Right to Left | peek … |
3️⃣ | Set state | Right to Left | set<…> … |
3️⃣ | Has state | Right to Left | has<…> … |
3️⃣ | Use identity | Right to Left | use<…> … |
3️⃣ | User error | Right to Left | error<…> … |
3️⃣ | User warning | Right to Left | warn<…> … |
3️⃣ | Symbol scope | Right to Left | scope … |
3️⃣ | Symbol record | Right to Left | symbol … |
3️⃣ | AST pivot | Right to Left | pivot … |
3️⃣ | AST place | Right to Left | place … |
3️⃣ | AST prepend | Right to Left | prepend … |
3️⃣ | AST append | Right to Left | append … |
3️⃣ | Repeat control | Right to Left | repeat … |
3️⃣ | Option control | Right to Left | opt … |
3️⃣ | Logical not | Right to Left | not … |
4️⃣ | Logical and | Left to Right | … and … |
5️⃣ | Logical or | Left to Right | … or … |
6️⃣ | Conditional | Right to Left | … then … else … |
7️⃣ | Assignment | Right to Left | … as … |
The assignment operator is a special binary operator that depends on a directive declaration for assigning to its left operand, an expression in its right operand.
Syntax:
token <0> FOO as BAR
node <0> FOO as BAR
alias token <0> FOO as BAR
alias node <0> FOO as BAR
Example:
token <0> T_FOO as BAR;
Assign a
BAR
expression toT_FOO
.
The conditional operator is the only ternary operator available in the language, when the first operand is true
, the second one is evaluated, otherwise, when a third operand exists, it will be evaluated instead.
Syntax:
FOO then BAR else BAZ
Example:
token <0> T_FOO as FOO then BAR else BAZ;
After an occurrence of
FOO
,BAR
is accepted, otherwise,BAZ
is accepted during the expression evaluation.
The else
syntax can be omitted when a third operand is not necessary, and in this case, the syntax is interchangeable with the and
expression.
Syntax:
FOO then BAR
Same as
FOO & BAR
.
There are three types of logical operators, as we will see below.
The logical or
operator is a binary operator used to evaluate a set of expressions and expect at least one of them to be true
.
Syntax:
FOO or BAR
Note:
or
and|
are interchangeable.
Example:
token <0> T_FOO as FOO | BAR | BAZ;
Accept an occurrence of
FOO
,BAR
orBAZ
during the expression evaluation.
The logical and
operator is a binary operator used to evaluate a set of expressions and expect all of them to be true
.
Syntax:
FOO and BAR
Note:
and
and&
are interchangeable.
Example:
token <0> T_FOO as FOO & BAR & BAZ;
Accept an occurrence of
FOO
,BAR
andBAZ
during the expression evaluation.
The logical not
operator is a unary operator used to evaluate an expression and invert the operation result, from true
to false
and vice versa.
Syntax:
not FOO
Example:
token <0> T_FOO as not BAR;
Accept anything but
BAR
during the expression evaluation.
There are two types of control operators, as we will see below.
The repeat
operator is a unary operator used to evaluate an expression, and in case of success, try to evaluate once more whenever the last evaluation is true
.
Syntax:
repeat FOO
Example:
token <0> T_FOO as repeat BAR;
Accept one or more occurrences of
BAR
during the expression evaluation.
The option (opt
) operator is a unary operator used to create an optional expression.
Syntax:
opt FOO
Example:
token <0> T_FOO as BAR & opt BAZ;
Accept an occurrence of
BAR
and optionallyBAZ
during the expression evaluation.
There are some operators for managing how the generated nodes must be inserted in the AST, let's take a look at these operators.
The append
operator is a unary operator used to attach a new node into the last AST child for the given directions when evaluating its operand as true
.
Syntax:
append FOO
append <IDENTITY> FOO
When no identity is provided, the directive identity is used for the new node.
Use left
, right
or next
when you want to be more specific, the default directions are right
and right
.
Syntax:
DIRECTION append DIRECTION EXPRESSION
DIRECTION append <IDENTITY> DIRECTION EXPRESSION
Example:
token <0> T_FOO as FOO;
node <1> N_FOO1 as append left T_FOO;
node <2> N_FOO2 as left append T_FOO;
node <2> N_FOO3 as left append left T_FOO;
The prepend
operator is a unary operator used to attach a new node in the first AST child for the given directions when evaluating its operand as true
.
Syntax:
prepend FOO
prepend <IDENTITY> FOO
When no identity is provided, the directive identity is used for the new node.
Use left
, right
or next
when you want to be more specific, the default directions are right
and right
.
DIRECTION prepend DIRECTION EXPRESSION
DIRECTION prepend <IDENTITY> DIRECTION EXPRESSION
Example:
token <0> T_FOO as FOO;
node <1> N_FOO1 as prepend left T_FOO;
node <2> N_FOO2 as left prepend T_FOO;
node <2> N_FOO3 as left prepend left T_FOO;
The place
operator is a unary operator used to wrap an expression that generates a new node and insert the resulting node in the AST replacing its original direction.
Syntax:
place FOO
Use left
, right
or next
when you want to be more specific, the default direction is right
.
Syntax:
place left FOO
place right FOO
place next FOO
Example:
token <0> T_FOO as FOO;
alias node N_BAR as append <0> right T_FOO;
node <1> N_FOO as place next N_BAR;
Place the generated node (that was expected to be an AST child on the right) as the next child of the active AST node, overwriting the
right
modifier in theappend
expression.
The pivot
operator is a unary operator used to insert a new node in the AST after evaluating its operand as true
. The pivoted node is a subtree containing the generated node before itself as the left child and the generated node after itself as the right child.
Syntax:
pivot FOO
pivot <identity> FOO
When no identity is provided, the directive identity is used for the new pivot node.
Example:
alias node N_FOO as append <0> FOO;
alias node N_BAR as append <1> BAR;
node <3> N_FOOBAR as N_FOO & pivot <2> (T_BAZ & N_BAR);
After evaluating
N_FOO
andN_BAR
, both generated nodes on theleft
andright
of the pivot operator will be attached in the new pivot node when the evaluation ofT_BAZ
istrue
, and then, the pivot node is inserted in the AST.
There are some operators for managing how the generated symbols must be inserted in the symbol table, let's take a look at these operators.
The symbol
operator is a unary operator used to insert a new symbol in the symbol table after evaluating its operand as true
.
Syntax:
symbol FOO
symbol <identity> FOO
When no identity is provided, the directive identity is used for the new symbol.
Example:
token <0> T_FOO as FOO;
node <0> N_FOO as symbol T_FOO;
Insert the
N_FOO
symbol in the symbol table whenT_FOO
is found.
The scope
operator is a unary operator used to generate a sub symbol table, if the new sub symbol table remains empty after the evaluation of its operand, it will be discarded and not linked to the active symbol record.
Syntax:
scope FOO
Example:
alias node N_FOO as symbol <0> FOO;
alias node N_BAR as symbol <1> BAR;
node <0> N_FOOBAR as N_FOO & scope N_BAR;
Insert the
N_FOO
symbol in the current symbol table and theN_BAR
symbol in the new sub symbol table.
The error
operator is a unary operator used to emit an error after evaluating its operand as true
, it doesn't stop the analysis process.
Syntax:
error <code> FOO
Note:
code
must be a number.
Example:
token <0> T_FOO as FOO;
node <0> N_FOO as error<1000> T_FOO;
Emit a new error (with code
1000
) every time theT_FOO
token is found.
The warn
operator is a unary operator used to emit a warning after evaluating its operand as true
, it doesn't stop the analysis process.
Syntax:
warn <code> FOO
Note:
code
must be a number.
Example:
token <0> T_FOO as FOO;
node <0> N_FOO as warn<1500> T_FOO;
Emit a new warning (with code
1500
) every time theT_FOO
token is found.
There are two types of state operators, as we will see below.
The set
operator is a unary operator used to set a new state in the parser, it's used together with the has
operator for conditional parsing.
Syntax:
set <state> FOO
Note:
state
must be a number.
Example:
token <0> T_FOO as set <99> FOO;
Set the state
99
whenFOO
is found.
The has
operator is a unary operator used to check whether the parser has an expected state before enabling the evaluation of its operand.
Syntax:
has <state> FOO
Note:
state
must be a number.
Example:
token <0> T_FOO as set<99> FOO;
token <1> T_BAR as has<99> BAR;
Look for
BAR
only when the state99
is defined, and the state99
is set only after findingFOO
during the expression evaluation.
The use
operator is a unary operator used to set a default identity in the parser.
Syntax:
use <identity> FOO
Note:
identity
must be a number.
Example:
token <auto> T_FOO as use <0> FOO;
Set identity
0
before trying to consumeFOO
, if no other identity was defined when consumingFOO
, the generated token will assume this default one.
The peek
operator is a unary operator used to test the next expression without advancing the parser consumption.
Syntax:
peek FOO
Example:
token <0> T_FOO as FOO & peek BAR;
A token
T_FOO
will be generated for each occurrence ofFOO
that precedesBAR
.
The uncase
operator is a unary operator used for case-insensitive expressions.
Syntax:
uncase FOO
Example:
token <0> T_FOO as uncase FOO;
A token
T_FOO
will be generated for any occurrence ofFOO
in a case-insensitive way.
The access operator is a binary operator used to make references for map
member entries.
Syntax:
FOO . BAR
Example:
token <auto> T_FOOBAR as map {
<0> FOO as FOO,
<1> BAR as BAR
};
node <0> N_FOOBAR as T_FOOBAR.FOO & repeat T_FOOBAR.BAR;
Accept an occurrence of
T_FOOBAR.FOO
and one or more occurrences ofT_FOOBAR.BAR
.
The grouping operator controls the evaluation precedence in expressions.
Syntax:
( FOOBAR )
Example:
token <0> T_FOOBAR as FOO & (repeat BAR & BAZ);
Accept an occurrence of
FOO
combined with one or more occurrences ofBAR
andBAZ
.