dmajda/pegjs — Issue #69: Redesign labels
Author: dmajda
Created: 2012-02-04 16:22:47+00:00
State: open

* Labels should basically work like block-scoped variables, where “blocks” are created implicitly by `/`, `&`, `!`, `?`, `*`, `+`, sequences, labels and actions. This means that:
* Actions should see all labels defined at the top level of the preceding expression or sequence *and* labels defined on levels above them.
* Predicates should see all labels defined at the top level of the sequence they are embedded in that precede the predicate *and* labels defined on levels above them.
* Examples:

/* Actions */

start = a:"a" { return a; } // OK (toplevel label)
start = (a:"a") { return a; } // OK (still toplevel lablel, parens just set precedence)
start = a:("a" / "b" / "c") { return a; } // OK (toplevel label)
start = a:"a" / b:"b" / c:"c" { return a + b + c; } // error (non-toplevel labels)
start = a:"a" b:"b" c:"b" { return a + b + c; } // OK (toplevel labels)
start = a:(b:"a") { return a; } // OK (toplevel label)
start = a:(b:"a") { return b; } // error (non-toplevel label)
start = a:&"a" . { return a; } // error (predicates won’t return any value (GH-66))
start = &(a:"a") . { return a; } // error (non-toplevel label)
start = a:!"a" . { return a; } // error (predicates won’t return any value (GH-66))
start = !(a:"a") . { return a; } // error (non-toplevel label)
start = a:"a"? { return a; } // OK (toplevel label)
start = (a:"a")? { return a; } // error (non-toplevel label)
start = a:"a"* { return a; } // OK (toplevel label)
start = (a:"a")* { return a; } // error (non-toplevel label)
start = a:"a"+ { return a; } // OK (toplevel label)
start = (a:"a")+ { return a; } // error (non-toplevel label)
start = a:("a" { }) { return a; } // OK (toplevel label)
start = (a:"a" { }) { return a; } // error (non-toplevel label)
start = a:"a" ({ return a; }) // OK (label one level up)
start = { return a; } a:"a" // error (label defined after use)

/* Predicates */

start = a:"a" &{ return a; } // OK (toplevel label)
start = (a:"a") &{ return a; } // OK (still toplevel lablel, parens just set precedence)
start = a:("a" / "b" / "c") &{ return a; } // OK (toplevel label)
start = a:"a" / b:"b" / c:"c" &{ return a + b + c; } // error (non-toplevel labels)
start = a:"a" b:"b" c:"b" &{ return a + b + c; } // OK (toplevel labels)
start = a:(b:"a") &{ return a; } // OK (toplevel label)
start = a:(b:"a") &{ return b; } // error (non-toplevel label)
start = a:&"a" . &{ return a; } // error (predicates won’t return any value (GH-66))
start = &(a:"a") . &{ return a; } // error (non-toplevel label)
start = a:!"a" . &{ return a; } // error (predicates won’t return any value (GH-66))
start = !(a:"a") . &{ return a; } // error (non-toplevel label)
start = a:"a"? &{ return a; } // OK (toplevel label)
start = (a:"a")? &{ return a; } // error (non-toplevel label)
start = a:"a"* &{ return a; } // OK (toplevel label)
start = (a:"a")* &{ return a; } // error (non-toplevel label)
start = a:"a"+ &{ return a; } // OK (toplevel label)
start = (a:"a")+ &{ return a; } // error (non-toplevel label)
start = a:("a" { }) &{ return a; } // OK (toplevel label)
start = (a:"a" { }) &{ return a; } // error (non-toplevel label)
start = a:"a" (&{ return a; } .) // OK (label one level up)
start = &{ return a; } a:"a" // error (label defined after use)

* Redefining a label should be an error.
* Shadowing a label should not be an error.
* [decision] Defining a label on a place nothing can possibly see it could be an error or warning.
* Depends on making `&...` and `!...` allowed only in sequences (#66)