module Pa_infix:sig..end
There are two ways of using this syntax extension.
Create a file, say my_syntax.ml, in which you open Pa_infix and
use the API below to set the operators you need, compile it to an
object file and pass the latter to camlp4. The advantage of this
approach is that the created module can be reused with various
source files. This is the recommended way of proceeding if you
want to define new operators to ship with your OCaml library.
This approach is particularly useful when you quickly need to
define prefix/postfix/infix operators in a given source file. The
syntax is INFIX ( op ), PREFIX ( op ), and POSTFIX ( op ) to
respectively define binary infix, unary prefix, and unary postfix
operators. These can be followed by a precedence specification:
HIGHEST, HIGHER ( op ), LEVEL ( op ), LOWER ( op ), or
LOWEST. Finally the associativity of infix operators can be set
with LEFTA (left associative), RIGHTA (right associative), or
NONA (non-associative). Operators at the same level must have
the same associativity so associativity is inherited from op
when you use LEVEL ( op ) (you cannot specify it).
Examples:
INFIX ( %+ ) RIGHTA HIGHER (+)
INFIX ( ^* ) LEVEL (+)
PREFIX ( /+/ )
POSTFIX ( /// ) LEVEL ( ! )
In case the concrete syntax conflicts with keywords in your code,
it can be disabled by passing the option -no-pa-infix to camlp4
(in which case only the first approach is possible).
Remarks
+, -,..., +.,...) cannot be
changed. This is to prevent strange bugs from occurring by
changing the meaning of code that does not use new operators
(e.g. one certainly does not want + to bind more tightly than
* or - to be right associative).
op, use the syntax let ( op ) args = expr --
just as you would do to redefine existing alphabetic operators
such as lsl,... Beware that prefix and postfxix operators bind
more tightly than function evaluation (think of the dereference
operator !). Use with care.
typeoperator =string
exception Not_operator of operator
Not_operator op is raised if the string op does not
designate a valid operator name.exception Forbidden of operator
Forbidden op is raised when the operator op belongs to the
operators which precedence or associativity one is not allowed
to change.module Level:sig..end
type kind =
| |
Prefix |
| |
Infix |
| |
Postfix |
exception Conflicting_kind of operator * kind * kind
Conflicting_kind op k0 k is raised when the kind of the operator
op was k0 but now trying to set it to k.exception Conflicting_level of operator * string * string
Conflicting_level op l0 l is raised when the level of the operator
op was l0 but now trying to set it to l.val infix : operator ->
?expr:(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.Loc.t -> Camlp4.PreCast.Syntax.Ast.expr) ->
Level.binary Level.t -> unitinfix op l defines the operator op as a binary infix
operator at level l.Not_operator if op is not a valid operator name.Forbidden if the operator op is not allowed.Conflicting_kind if there is a conflict with the kind of op.Conflicting_level if there is a conflict with the level of op.Level.Bad_arity if a '_a Level.t is given which is not
a Level.binary Level.t.expr : the function performing the operator subsititution:
the expression x op y is transformed into expr x y _loc. It
is the rewriting rule associated to x op y. Note that this
can be used to simplify expressions x op y but defines in no
way the function op ; if you want op also to work in
context where no arguments are provided immediately, you need to
bind op to a compatible function: let (op) = .... The
default is to keep the function application: fun x y _loc ->
<:expr< $lid:op$ $x$ $y$ >>.val prefix : ?expr:(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.Loc.t -> Camlp4.PreCast.Syntax.Ast.expr) ->
?level:Level.unary Level.t -> operator -> unitprefix op l define the operator op as a prefix operator at
level l. Remark: if you use a prefix operator between braces,
make sure to put spaces between around the expressions. For
example, assuming you set / as prefix, (/4) is parsed as
"(/", "4" and ")", you have to write ( /4 ) or ( / 4 ) for
/ to be considered as a prefix operator. Note that, usually,
you will not need any braces as prefix operators bind more
tightly than evaluation: f /4 5 will be interpreted as f ( /4 ) 5.Not_operator if op is not a valid operator name.Forbidden if the operator op is not allowed.Conflicting_kind if there is a conflict with the kind of op.Conflicting_level if there is a conflict with the level of op.Level.Bad_arity if a '_a Level.t is given which is not
a Level.unary Level.t.expr : the function performing the operator subsititution:
the expression op x is transformed into expr x _loc.
Default: fun x _loc -> <:expr< $lid:op$ $x$ >>.val postfix : ?expr:(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.Loc.t -> Camlp4.PreCast.Syntax.Ast.expr) ->
?level:Level.unary Level.t -> operator -> unitpostfix op l define the operator op as a postfix operator at
level l. The same remarks as for prefix apply.Not_operator if op is not a valid operator name.Forbidden if the operator op is not allowed.Conflicting_kind if there is a conflict with the kind of op.Conflicting_level if there is a conflict with the level of op.Level.Bad_arity if a '_a Level.t is given which is not a
Level.unary Level.t.expr : the function performing the operator subsititution:
the expression x op is transformed into expr x _loc.
Default: fun x _loc -> <:expr< $lid:op$ $x$ >>.val assoc : operator -> Level.assocassoc op returns the associativity of the operator op.Not_operator if op is not a valid operator name.val level : operator -> 'a Level.tpos op returns the (default or assigned) level of the operator op.Not_operator if op is not a valid operator name.val kind : operator -> kindkind op returns the (default or assigned) kind of the operator op.Not_operator if op is not a valid operator name.val is_operator : operator -> boolis_operator op tells whether the string op can be used as an
operator.val is_set : operator -> boolis_set op tells whether the operator op has been set using
one of the functions of this API.Not_operator if op is not a valid operator name.val handle_error : ('a -> 'b) -> 'a -> 'bhandle_error f a applies f to x and returns the result.
If an exception of this library is raised, it prints a message
describing the error and exits with code 2.