Reserved Notation"g || t |- x < y"(at level10).InductiveSubtypeOf:GammaEnv->ThetaEnv->UnsafeType->UnsafeType->Set:=|SubRefl:forall(gamma:GammaEnv)(theta:ThetaEnv)(u:UnsafeType),gamma||theta|-u<uwhere"g || t |- x < y":=(SubtypeOfgtxy).
gives the following error:
Syntax error: '<' expected after [constr:operconstr level 200] (in
[constr:operconstr])
I get a similar error if I use <: in place of <.
But this code works fine:
Reserved Notation"g || t |- x << y"(at level10).InductiveSubtypeOf:GammaEnv->ThetaEnv->UnsafeType->UnsafeType->Set:=|SubRefl:forall(gamma:GammaEnv)(theta:ThetaEnv)(u:UnsafeType),gamma||theta|-u<<uwhere"g || t |- x << y":=(SubtypeOfgtxy).
Why? Is there a precedence setting that can be changed to allow <
or <: in notation? Is there built-in syntax that I'm colliding
with, and need to watch for when defining notations?
Answer
Coq uses an LL1 parser to process notations. It also can output the
grammar. So, let's check what we are getting with the following
Reserved Notation"g || t |- x < y" (at level10).
Entry constris
[ LEFTA
[ "@"; global; univ_annot
| term LEVEL "8" ] ]
and lconstr is
[ LEFTA
[ term LEVEL "200" ] ]
where binder_constr is
[ LEFTA
[ "exists2"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; ","; term LEVEL
"200"; "&"; term LEVEL "200"
| "exists2"; "'"; pattern LEVEL "0"; ","; term LEVEL "200"; "&"; term LEVEL
"200"
| "exists2"; name; ":"; term LEVEL "200"; ","; term LEVEL "200"; "&"; term
LEVEL "200"
| "exists2"; name; ","; term LEVEL "200"; "&"; term LEVEL "200"
| "exists"; "!"; open_binders; ","; term LEVEL "200"
| "exists"; open_binders; ","; term LEVEL "200"
| "IF"; term LEVEL "200"; "then"; term LEVEL "200"; "else"; term LEVEL
"200"
| "forall"; open_binders; ","; term LEVEL "200"
| "fun"; open_binders; "=>"; term LEVEL "200"
| "let"; "fix"; fix_decl; "in"; term LEVEL "200"
| "let"; "cofix"; cofix_body; "in"; term LEVEL "200"
| "let"; "'"; pattern LEVEL "200"; ":="; term LEVEL "200"; "in"; term LEVEL
"200"
| "let"; "'"; pattern LEVEL "200"; ":="; term LEVEL "200"; case_type; "in";
term LEVEL "200"
| "let"; "'"; pattern LEVEL "200"; "in"; pattern LEVEL "200"; ":="; term
LEVEL "200"; case_type; "in"; term LEVEL "200"
| "let"; name; binders; let_type_cstr; ":="; term LEVEL "200"; "in"; term
LEVEL "200"
| "let"; [ "("; LIST0 name SEP ","; ")" | "()" ]; as_return_type; ":=";
term LEVEL "200"; "in"; term LEVEL "200"
| "if"; term LEVEL "200"; as_return_type; "then"; term LEVEL "200"; "else";
term LEVEL "200"
| "fix"; fix_decls
| "cofix"; cofix_decls ] ]
and term is
[ "200" RIGHTA
[ binder_constr ]
| "100" RIGHTA
[ SELF; "<:"; term LEVEL "200"
| SELF; "<<:"; term LEVEL "200"
| SELF; ":"; term LEVEL "200"
| SELF; ":>" ]
| "99" RIGHTA
[ SELF; "->"; term LEVEL "200" ]
| "95" RIGHTA
[ SELF; "<->"; NEXT ]
| "90" RIGHTA
[ ]
| "85" RIGHTA
[ SELF; "\\/"; term LEVEL "85" ]
| "80" RIGHTA
[ SELF; "/\\"; term LEVEL "80" ]
| "75" RIGHTA
[ "~"; term LEVEL "75" ]
| "70" RIGHTA
[ SELF; ">"; NEXT
| SELF; ">="; NEXT
| SELF; "<"; NEXT; "<="; NEXT
| SELF; "<"; NEXT; "<"; NEXT
| SELF; "<"; NEXT
| SELF; "<="; NEXT; "<"; NEXT
| SELF; "<="; NEXT; "<="; NEXT
| SELF; "<="; NEXT
| SELF; "<>"; NEXT; ":>"; NEXT
| SELF; "<>"; NEXT
| SELF; "="; NEXT; "="; NEXT
| SELF; "="; NEXT; ":>"; NEXT
| SELF; "="; NEXT ]
| "60" RIGHTA
[ SELF; "++"; term LEVEL "60"
| SELF; "::"; term LEVEL "60" ]
| "50" LEFTA
[ SELF; "||"; NEXT
| SELF; "-"; NEXT
| SELF; "+"; NEXT ]
| "40" LEFTA
[ SELF; "&&"; NEXT
| SELF; "/"; NEXT
| SELF; "*"; NEXT ]
| "35" RIGHTA
[ "/"; term LEVEL "35"
| "-"; term LEVEL "35" ]
| "30" RIGHTA
[ SELF; "^"; term LEVEL "30" ]
| "10" LEFTA
[ SELF; "||"; term LEVEL "200"; "|-"; term LEVEL "200"; "<"; NEXT
| SELF; LIST1 arg
| "@"; global; univ_annot; LIST0 NEXT
| "@"; pattern_ident; LIST1 identref ]
| "9" LEFTA
[ ".."; term LEVEL "0"; ".." ]
| "8" LEFTA
[ ]
| "1" LEFTA
[ SELF; ".("; "@"; global; LIST0 (term LEVEL "9"); ")"
| SELF; ".("; global; LIST0 arg; ")"
| SELF; "%"; IDENT ]
| "0" LEFTA
[ IDENT "ltac"; ":"; "("; ltac_expr; ")"
| "("; term LEVEL "200"; ","; term LEVEL "200"; ","; LIST1 (term LEVEL
"200") SEP ","; ")"
| "("; term LEVEL "200"; ","; term LEVEL "200"; ")"
| "("; term LEVEL "200"; ")"
| "{|"; record_declaration; '|}'
| "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL
"200"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL
"200"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "&";
term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "&";
term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "}"
| "{"; binder_constr; "}"
| "`{"; term LEVEL "200"; "}"
| "`("; term LEVEL "200"; ")"
| atomic_constr
| term_match
| test_array_opening; "["; "|"; array_elems; "|"; lconstr; type_cstr;
test_array_closing; "|"; "]"; univ_annot ] ]
200 is the default precedence level for inner subexpressions.
Taking into account the fact that a lower level binds more tightly
than a higher level and the fact that the level of < is 70 (see
Coq.Init.Notations), we can
deduce that Coq is trying to parse the x < y part as a
subexpression for x, consuming the < token, hence the error
message.
To remedy the situation we can explicitly disallow parsing the third
parameter as the less-than expression by assigning x higher
precedence, i.e. a lower level.
Reserved Notation"g || t |- x < y" (at level10, x at level69).
Entry constris
[ LEFTA
[ "@"; global; univ_annot
| term LEVEL "8" ] ]
and lconstr is
[ LEFTA
[ term LEVEL "200" ] ]
where binder_constr is
[ LEFTA
[ "exists2"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; ","; term LEVEL
"200"; "&"; term LEVEL "200"
| "exists2"; "'"; pattern LEVEL "0"; ","; term LEVEL "200"; "&"; term LEVEL
"200"
| "exists2"; name; ":"; term LEVEL "200"; ","; term LEVEL "200"; "&"; term
LEVEL "200"
| "exists2"; name; ","; term LEVEL "200"; "&"; term LEVEL "200"
| "exists"; "!"; open_binders; ","; term LEVEL "200"
| "exists"; open_binders; ","; term LEVEL "200"
| "IF"; term LEVEL "200"; "then"; term LEVEL "200"; "else"; term LEVEL
"200"
| "forall"; open_binders; ","; term LEVEL "200"
| "fun"; open_binders; "=>"; term LEVEL "200"
| "let"; "fix"; fix_decl; "in"; term LEVEL "200"
| "let"; "cofix"; cofix_body; "in"; term LEVEL "200"
| "let"; "'"; pattern LEVEL "200"; ":="; term LEVEL "200"; "in"; term LEVEL
"200"
| "let"; "'"; pattern LEVEL "200"; ":="; term LEVEL "200"; case_type; "in";
term LEVEL "200"
| "let"; "'"; pattern LEVEL "200"; "in"; pattern LEVEL "200"; ":="; term
LEVEL "200"; case_type; "in"; term LEVEL "200"
| "let"; name; binders; let_type_cstr; ":="; term LEVEL "200"; "in"; term
LEVEL "200"
| "let"; [ "("; LIST0 name SEP ","; ")" | "()" ]; as_return_type; ":=";
term LEVEL "200"; "in"; term LEVEL "200"
| "if"; term LEVEL "200"; as_return_type; "then"; term LEVEL "200"; "else";
term LEVEL "200"
| "fix"; fix_decls
| "cofix"; cofix_decls ] ]
and term is
[ "200" RIGHTA
[ binder_constr ]
| "100" RIGHTA
[ SELF; "<:"; term LEVEL "200"
| SELF; "<<:"; term LEVEL "200"
| SELF; ":"; term LEVEL "200"
| SELF; ":>" ]
| "99" RIGHTA
[ SELF; "->"; term LEVEL "200" ]
| "95" RIGHTA
[ SELF; "<->"; NEXT ]
| "90" RIGHTA
[ ]
| "85" RIGHTA
[ SELF; "\\/"; term LEVEL "85" ]
| "80" RIGHTA
[ SELF; "/\\"; term LEVEL "80" ]
| "75" RIGHTA
[ "~"; term LEVEL "75" ]
| "70" RIGHTA
[ SELF; ">"; NEXT
| SELF; ">="; NEXT
| SELF; "<"; NEXT; "<="; NEXT
| SELF; "<"; NEXT; "<"; NEXT
| SELF; "<"; NEXT
| SELF; "<="; NEXT; "<"; NEXT
| SELF; "<="; NEXT; "<="; NEXT
| SELF; "<="; NEXT
| SELF; "<>"; NEXT; ":>"; NEXT
| SELF; "<>"; NEXT
| SELF; "="; NEXT; "="; NEXT
| SELF; "="; NEXT; ":>"; NEXT
| SELF; "="; NEXT ]
| "69" RIGHTA
[ ]
| "69" RIGHTA
[ ]
| "69" RIGHTA
[ ]
| "69" RIGHTA
[ ]
| "60" RIGHTA
[ SELF; "++"; term LEVEL "60"
| SELF; "::"; term LEVEL "60" ]
| "50" LEFTA
[ SELF; "||"; NEXT
| SELF; "-"; NEXT
| SELF; "+"; NEXT ]
| "40" LEFTA
[ SELF; "&&"; NEXT
| SELF; "/"; NEXT
| SELF; "*"; NEXT ]
| "35" RIGHTA
[ "/"; term LEVEL "35"
| "-"; term LEVEL "35" ]
| "30" RIGHTA
[ SELF; "^"; term LEVEL "30" ]
| "10" LEFTA
[ SELF; "||"; term LEVEL "200"; "|-"; term LEVEL "69"; "<"; NEXT
| SELF; LIST1 arg
| "@"; global; univ_annot; LIST0 NEXT
| "@"; pattern_ident; LIST1 identref ]
| "9" LEFTA
[ ".."; term LEVEL "0"; ".." ]
| "8" LEFTA
[ ]
| "1" LEFTA
[ SELF; ".("; "@"; global; LIST0 (term LEVEL "9"); ")"
| SELF; ".("; global; LIST0 arg; ")"
| SELF; "%"; IDENT ]
| "0" LEFTA
[ IDENT "ltac"; ":"; "("; ltac_expr; ")"
| "("; term LEVEL "200"; ","; term LEVEL "200"; ","; LIST1 (term LEVEL
"200") SEP ","; ")"
| "("; term LEVEL "200"; ","; term LEVEL "200"; ")"
| "("; term LEVEL "200"; ")"
| "{|"; record_declaration; '|}'
| "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL
"200"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL
"200"; "&"; term LEVEL "200"; "}"
| "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "&"; term LEVEL
"200"; "}"
| "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "&";
term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "&";
term LEVEL "200"; "}"
| "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "|"; term LEVEL "200"; "}"
| "{"; term LEVEL "99"; "}"
| "{"; binder_constr; "}"
| "`{"; term LEVEL "200"; "}"
| "`("; term LEVEL "200"; ")"
| atomic_constr
| term_match
| test_array_opening; "["; "|"; array_elems; "|"; lconstr; type_cstr;
test_array_closing; "|"; "]"; univ_annot ] ]