Patrick, Nice work! I'm still digesting your full mail.
With respect to the pattern-names-as-type problem, I don't know if restricting the pattern name to be an identifier is the right thing to do. Would we be adding that restriction for all fn items, or just those that appear in traits? There are default methods to consider. I think it'd be best to have the same rules for all fn items (and maybe those rules should be: no patterns, those can only appear in closures). The other option is just to require parameter names on all method declarations, which would be more consistent, but would also sometimes be annoying for lightweight traits where the parameter names are uninteresting. Finally, one could imagine requiring that patterns be parenthesized or something like that? I confess that I sometimes find the current syntax hard to parse, but I think that's at least partially because of the old mode syntax (which is indeed ambiguous), parentheses might make it clearer. But I think I wouldn't want them to be required in the `|...|` closure syntax, so for consistency this option is probably out. Niko On Wed, Apr 24, 2013 at 10:06 PM, Patrick Walton <[email protected]>wrote: > I've refactored the Rust grammar to get it as close to LL(1) as I could. I > made some minor language changes along the way which should not break code, > but there are a few things that are still preventing me from making it > LL(1): > > 1. Explicit self and patterns-as-arguments require two tokens of lookahead > to find the `self` (or `mut` or lifetime). > > fn foo(&self, ...) vs. fn foo(&a: &int) { ... } > > This is because arguments are patterns, and `&a` is a valid pattern. > > 2. There is a production called "maybe-named argument", which is part of > the trait declaration form. (It also shows up in function types.) This > allows you to write: > > trait Foo { > fn bar(&int, &int); > } > > Instead of: > > trait Foo { > fn bar(x: &int, y: &int); > } > > However, because arguments can be patterns, lookahead is required to > distinguish between that and this: > > trait Foo { > fn bar(&x: &int, &y: int); > } > > I believe this can actually be *unbounded* lookahead. Consider: > > trait Foo { > fn bar(&&&&&&&&&&x: &&&&&&&&&&int); > } > > Versus: > > trait Foo { > fn bar(&&&&&&&&&&int); > } > > This has a relatively straightforward fix though: just restrict the > argument name to be an identifier. There is little need for the pattern > form here. This reduces the complexity to LL(2); I haven't investigated > whether it can be reduced further. > > 3. `unsafe` blocks and `unsafe` function declarations are both allowed > inside blocks, and therefore two tokens of lookahead are required. > > fn foo() { > unsafe fn bar() { ... } > } > > Versus: > > fn foo() { > unsafe { ... } > } > > The parser needs to look ahead two tokens to find the `fn` or `{` keyword. > > These were the only warnings that the Python yapps2 module emitted when > compiling the Rust grammar, after suitable refactoring. My general feeling > is that, given how valuable explicit self and argument patterns are, LL(2) > is okay, especially if we turn out to be LALR(1). Others may feel > differently, however; thoughts? > > Patrick > ______________________________**_________________ > Rust-dev mailing list > [email protected] > https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev> >
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
