add_infix : string * int * HOLgrammars.associativity -> unit
<str1> s <str2>will be parsed as
s <t1> <t2>where <str1> and <str2> have been parsed to two terms <t1> and <t2>. The parsing process does not pay any attention to whether or not s corresponds to a constant or not. This resolution happens later in the parse, and will result in either a constant or a variable with name s. In fact, if this name is overloaded, the eventual term generated may have a constant of quite a different name again; the resolution of overloading comes as a separate phase (see the entry for overload_on).
It is also possible that the choice of string s will result in subsequent attempts to call the term parser failing due to precedence conflicts.
- add_infix ("+", 500, HOLgrammars.LEFT); > val it = () : unit - val t = Term`x + y`; <<HOL message: inventing new type variable names: 'a, 'b, 'c.>> > val t = `x + y` : termWe can confirm that this new infix has indeed been parsed that way by taking the resulting term apart:
- dest_comb t; > val it = (`$+ x`, `y`) : term * termWith its new status, + has to be ``quoted'' with a dollar-sign if we wish to use it in a position where it is not an infix, as in the binding list of an abstraction:
- Term`\$+. x + y`; <<HOL message: inventing new type variable names: 'a, 'b, 'c.>> > val it = `\$+. x + y` : term - dest_abs it; > val it = (`$+`,`x + y`) : term * termThe generation of three new type variables in the examples above emphasises the fact that the terms in the first example and the body of the second are really no different from f x y (where f is a variable), and don't have anything to do with the constant for addition from arithmeticTheory. The new + infix is left associative:
- Term`x + y + z`; <<HOL message: inventing new type variable names: 'a, 'b.>> > val it = `x + y + z` : term - dest_comb it; > val it = (`$+ (x + y)`, `z`) : term * termIt is also more tightly binding than /\ (which has precedence 400 by default):
- Term`p /\ q + r`; <<HOL message: inventing new type variable names: 'a, 'b.>> > val it = `p /\ q + r` : term - dest_comb it; > val it = (`$/\ p`, `q + r`) : term * termAn attempt to define a right associative operator at the same level fails:
Lib.try add_infix("-", 500, HOLgrammars.RIGHT); Exception raised at Parse.add_infix: Grammar Error: Attempt to have differently associated infixes (RIGHT and LEFT) at same levelSimilarly we can't define an infix at level 900, because this is where the (true prefix) rule for logical negation (~) is.
- Lib.try add_infix("-", 900, HOLgrammars.RIGHT); Exception raised at Parse.add_infix: Grammar Error: Attempt to have different forms at same levelFinally, an attempt to have a second + infix at a different precedence level causes grief when we later attempt to use the parser:
- add_infix("+", 400, HOLgrammars.RIGHT); > val it = () : unit - Term`p + q`; ! Uncaught exception: ! HOL_ERR <poly> - Lib.try Term`p + q`; Exception raised at Parse.Term: Grammar introduces precedence conflict between tokens + and +