Module Pa_infix


module Pa_infix: sig .. end
Syntax extension module to change the priority or associativity of unary and binary operators. As these characteristics of operators are global for a source file, the API also checks that no conflicts occur.

There are two ways of using this syntax extension.

1. Using the API

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.

2. Using the concrete syntax

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




Pa_infix API


type operator = string 
Operators represented as their concrete string syntax.
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
Level of precedence of operators (also specifies their associativity).

type kind =
| Prefix
| Infix
| Postfix
Possible kinds of operators.
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 -> unit
infix op l defines the operator op as a binary infix operator at level l.
Raises
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 -> unit
prefix 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.
Raises
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 -> unit
postfix op l define the operator op as a postfix operator at level l. The same remarks as for prefix apply.
Raises
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.assoc
assoc op returns the associativity of the operator op.
Raises Not_operator if op is not a valid operator name.
val level : operator -> 'a Level.t
pos op returns the (default or assigned) level of the operator op.
Raises Not_operator if op is not a valid operator name.
val kind : operator -> kind
kind op returns the (default or assigned) kind of the operator op.
Raises Not_operator if op is not a valid operator name.
val is_operator : operator -> bool
is_operator op tells whether the string op can be used as an operator.
val is_set : operator -> bool
is_set op tells whether the operator op has been set using one of the functions of this API.
Raises Not_operator if op is not a valid operator name.
val handle_error : ('a -> 'b) -> 'a -> 'b
handle_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.