We have a problem with Typer's syntax.
As you may know, the sexp reader turn infix operators into "sexp-style" thingies by adding underscores between the various matching "infix" elements.
To be more concrete, the syntax
let decl in exp
is read (according to the precedence table used by default) as if we had written
let_in_ decl exp
Also, usually tokens are separated by spaces, except for those rare tokens declared as single-char tokens (by default, this is just the chars in "{}();,", IIRC), so
a;b;c
is actually read as five tokens equivalent to
_;_ a b c
For this to work, we need to treat _ as special, so that "_;_" is read as a single token and not as "_ ; _".
Now here's the problem: Typer's syntax also uses _ as a token and having to always surround it with spaces is annoying.
For example: in explicit arguments, I want to be able to say
length (α := Int) ...
and hence pass the argument by name, but I also want to be able to write
length (_ := Int) ...
which should mean the arg is passed positionally. But in reality the above leads to a parsing error because the ")" has no matching open paren: the "(_" is treated as a single token with no particular syntactic or semantic meaning. So it's parsed basically in the same way as something like
length blabla := Int ) ...
So currently, in the tests, I had to write
case t | triplet ( _ := af) ( _ := bf) ( _ := cf) => bf;
which is hideous, and if the user writes the "natural" thing he gets an incomprehensible error (something like parsing stopped before the end). I can see how to improve the error message, but I'd rather support the "natural" syntax.
Any ideas how to tweak the system to solve this problem?
So far my best idea is to make _ not stick to parentheses, so you can't write a token like (_). This solves the problem at least for parentheses. But the same problem would occur with brackets if we declare them as single-chars. So maybe another approach is to get rid of the stickiness of _ altogether and invent another syntax to write tokens such as _;_ and [_].
Stefan
PS: Note that _ is already non-sticky w.r.t braces because braces are parsed/matched earlierm (in the "prelexer"), before we tokenize the stream.
Afficher les réponses par date
Why not change the sticking character instead of being "_" it could be something like '#' or '$' ?
We have already discussed having "##" for builtin constructs. It might make it even more consistent to use it for everything the compiler uses under the hood.
##; ##+ ##let_in ##| ##cons ##inductive
Why not change the sticking character instead of being "_" it could be something like '#' or '$' ?
We have already discussed having "##" for builtin constructs. It might make it even more consistent to use it for everything the compiler uses under the hood.
##; ##+ ##let_in ##| ##cons ##inductive
Re-using existing special syntax would be good, indeed. But I see a few problems with this solution:
- normal user programs will occasionally want to manipulate and define infix operators, so it shouldn't be too ugly. - programs will also want to define brand new infix operators (e.g. _++_ for concatenation), and since these wouldn't be built-in, using ## would be odd.
In the mean time, I thought about taking inspiration, again, from Lisp. To write "odd" symbols, Common Lisp's reader supports the syntax |...|, so we could do something similar (tho not using |...| since we need | for other purposes). In Emacs Lisp, |...| is not supported, but instead you can -escape any char, so in order to write the symbol composed of 3 spaces (i.e. | |) you can write \ \ \ .
So we could ask the user to write ; to get a semi-colon which is not a single-char token. IOW the user would have to write _;_ instead of the current _;_.
We already support -escaping inside strings in the (pre)lexer, so it would be fairly natural to extend this escaping to also work in symbols.
Stefan