Skip to content

Latest commit

 

History

History
620 lines (387 loc) · 14.4 KB

operators.md

File metadata and controls

620 lines (387 loc) · 14.4 KB

XCHEME - Operators

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.

Unary operators

A unary operator requires a single operand always after the operator.

operator FOO

For example, opt FOO.

Binary operators

A binary operator requires two operands, one before and another one after the operator.

FOO operator BAR

For example, FOO & BAR or FOO and BAR.

Ternary operators

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.

Operator precedence

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 …

Assignment operator

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 to T_FOO.

Back to table

Conditional operator

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.

Back to table

Logical operators

There are three types of logical operators, as we will see below.

Logical or

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 or BAZ during the expression evaluation.

Back to table

Logical and

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 and BAZ during the expression evaluation.

Back to table

Logical not

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.

Back to table

Control operators

There are two types of control operators, as we will see below.

Repeat operator

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.

Back to table

Opt operator

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 optionally BAZ during the expression evaluation.

Back to table

AST operators

There are some operators for managing how the generated nodes must be inserted in the AST, let's take a look at these operators.

Append operator

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;

Back to table

Prepend operator

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;

Back to table

Place operator

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 the append expression.

Back to table

Pivot operator

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 and N_BAR, both generated nodes on the left and right of the pivot operator will be attached in the new pivot node when the evaluation of T_BAZ is true, and then, the pivot node is inserted in the AST.

Back to table

Symbol tables

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.

Symbol operator

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 when T_FOO is found.

Back to table

Scope operator

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 the N_BAR symbol in the new sub symbol table.

Back to table

Error operator

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 the T_FOO token is found.

Back to table

Warn operator

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 the T_FOO token is found.

Back to table

State operators

There are two types of state operators, as we will see below.

Set operator

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 when FOO is found.

Back to table

Has operator

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 state 99 is defined, and the state 99 is set only after finding FOO during the expression evaluation.

Back to table

Use operator

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 consume FOO, if no other identity was defined when consuming FOO, the generated token will assume this default one.

Back to table

Peek operator

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 of FOO that precedes BAR.

Back to table

Uncase operator

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 of FOO in a case-insensitive way.

Back to table

Access operator

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 of T_FOOBAR.BAR.

Back to table

Grouping operator

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 of BAR and BAZ.

Back to table

Next steps

License

MIT