keyword can be used for such definitions. When a new level is created, an associativity for this level has to be additionally specified
by using corresponding keyword ("\lstinline|infix|" for non-associative levels, "\lstinline|infixr|"~--- for levels with right
associativity, and "\lstinline|infixl|"~--- for levels with left associativity).
When public infix operators are exported, their relative precedence levels and associativity are exported as well; since not all
custom infix definitions may be made public some levels may disappear from the export. For example, let us have the following definitions:
\begin{lstlisting}
infixl ** before * (x, y) {...}
public infixr *** before ** (x, y) {...}
\end{lstlisting}
Here in the top scope for the compilation unit we have two additional precedence levels: one for the "\lstinline|**|" and another for the "\lstinline|***|".
However, as "\lstinline|**|" is not exported its precedence level will be forgotten during the import. Thus, only the precedence level for
"\lstinline|***|" will be created during the import as if is was defined at the level "\lstinline|before *|".
Respectively, multiple imports of units with custom infix operators will modify the precedence level in the order of their import. For example,
if there are two units "\lstinline|A|" and "\lstinline|B|" with declarations "\lstinline|infixl ++ before +|" and "\lstinline|infixl +++ before +|"
Syntax definition extension represents an alternative simplified syntax for parsers written using standard unit \lstinline|Ostap| (see Section~\ref{sec:ostap}).
Syntax expressions can be used wherever regular expressions are allowed. Each syntax expressions is expanded in a certain combination of \lstinline|Ostap| primitives.
For example,
\begin{lstlisting}
fun sum (str) {
parseString (
syntax (l=DECIMAL token["+"] r=DECIMAL eof {
stringInt (l) + stringInt (r)
}),
str
)
}
\end{lstlisting}
defines a function which parses its arguments into an expression \lstinline|"l + r"|, where \lstinline|l| and \lstinline|r| are decimal literals, and evaluates its value.
A syntax expression itself is a sequence of alternatives, and each alternative is a sequential composition (\nonterm{syntaxSeq}) of primitive parsers equipped with optional
semantic action (a \emph{general} expression in curly brackets).
A primitive parser is either an l-indentfier (possibly supplied with arguments), or a \emph{general} expression, surrounded by brackets \term{\$(}..\term{)},
or a \emph{syntax} expression, surrounded by round brackets. Note, the arguments for primitive parsers in syntax expressions are surrounded by
\term{[}..\term{]} unlike general expressions; thus
\begin{lstlisting}
x ("a")
\end{lstlisting}
means a sequential composition of \lstinline|x| and "\lstinline|a|", not a combinator \lstinline|x| applied to "\lstinline|a|".
A primitive parser can be followed by one of postfix operators ("\term{*}", "\term{+}", or "\term{?}"), corresponding
to "\lstinline|rep0|", "\lstinline|rep|", or "\lstinline|opt|" combinators of \lstinline|Ostap| respectively, for example
\begin{lstlisting}
token["a"]+
identifier?
\end{lstlisting}
A value recognized by a primitive parser can be matched against a pattern, for example
\begin{lstlisting}
value=(identifier | constant)
h:tl=item+
\end{lstlisting}
The bindings provided by pattern-matching can be used in semantic actions.
Finally, if no semantic action is given, a sequential syntax expression returns a tuple of its components. However, if a parser
in a sequential composition is preceded by "\term{-}" then its value is not included into the default result. Thus,
\begin{lstlisting}
parse -eof
\end{lstlisting}
returns what "\lstinline|parse|" recognized; the input stream is parsed against "\lstinline|eof|", but the result of "\lstinline|eof|"