On 2/19/13, Beni Cherniavsky-Paskin <c...@users.sf.net> wrote: > Here is yet another idea for opening multiple levels on one line, that does > NOT involve column counting, only comparison of leading whitespaces. > > It's a backward-compatible extension to SUBLIST (similarly applicable to > any competing FOOLIST semantics), so we could leave it undecided for now, > and legalize it later. > > $ lets one open an inner list on one line, but currently it's only usable > when this list is the last element of the containing list: > > outer1 outer2 $ inner1 > ! inner2 > > You cannot express (outer1 outer2 (inner1 inner2) outer3) > without giving up on use of $. > > The proposal is to allow an unmatched dedent after inner2, and have that > return you to the outer level: > > outer1 outer2 $ inner1 > ! ! inner2 > ! outer3 > > which would be equivallent to: > > outer1 outer2 > ! inner1 > ! ! inner2 > ! outer3 > > More formally (described for simplicity in terms of numeric indentation > levels; easily doable in terms of exact substrings): > > - Every $ pushes a "?" placeholder onto the stack of known indent levels. > - As before, increases in indentation push a specific number onto the > stack. > - Dedents matching a level on the stack are handled as before, closing all > levels to the right, whether specific or placeholders. > - A dedent that doesn't match any specific level is *only* allowed if there > is at least one placeholder between the closest specific levels. All > higher levels are closed, and the *rightmost* (see rationate at end) of > these placeholders is converted to the specific level seen. > Let's say you had (10 ? ? 16) on the stack and you encounter a line > starting with 14 spaces. This closes 16 and the new stack is (10 ? 14). > A following 13 line would close 14 and leave (10 13), and then a > following 12 line would be an error.
I think it's also important to consider the "SAME" (as opposed to INDENT or DEDENT) token. In particular: x ! foo $ bar ! a b ==> (x (foo bar) (a b) ) Since the INDENT/SAME/DEDENT decision is based on the indentation stack, I think we should specify it as follows: 1. Every $ adds a ? to the indentation stack, and emits an INDENT. 2. On encountering an EOL, slurp the indentation. 3. If the indentation is greater than the topmost non-? stack entry, push its indentation level on the stack and consider it an INDENT. 4. If the indentation is equal to the topmost non-? stack entry, pop off ? stack entries (emitting a DEDENT for each). If there are no ? on the stack top, emit a SAME. 5. If the indentation is less than the topmost non-? stack entry, pop off ? stack entries (emitting a DEDENT for each) until you reach a state where the topmost non-? stack entry is less than or equal to the indentation. 5.1. If the topmost non-? stack entry is equal to the indentation, pop off ? stack entries (emitting a DEDENT for each). 5.2. if the topmost non-? stack entry is less than the indentation, and there is at least one ? entry, pop off the topmost ? entry and replace it with the current indentation (do not emit any INDENT or DEDENT tokens). 5.2. Otherwise, error! So, let's consider this classic SUBLIST text: probe $ call/cc $ lambda (exit) $ cond foo? $ exit 1 bar? $ 2 ==> probe INDENT call/cc INDENT lambda (exit) INDENT cond ; at this stage, stack is (0 ? ? ?) INDENT foo? INDENT exit 1 ; at this stage, stack is (0 ? ? ? 2 ?) ; it sees an indent of 2, so it emits a DEDENT here ; via rule #4. DEDENT bar? INDENT 2 ; at this stage, stack is (0 ? ? ? 2 ?) ; an empty line may be considered an indent of 0, ; so insert 5 DEDENT's DEDENT DEDENT DEDENT DEDENT DEDENT ==> probe ! call/cc ! ! lambda (exit) ! ! ! cond ! ! ! ! foo? ! ! ! ! ! exit 1 ; 5 indent's so far, so 5 levels, seems right ! ! ! ! bar? ! ! ! ! ! 2 ; 5 dedents after this, so we close!! -- Looks about right. Now the main reason to implement SUBLIST this way is, of course, the bane of indentation syntax, LET: let !!$ x $ compute 'x !!!!y $ compute 'y !!use x y ==> let ; the first indent below is the "real" indent INDENT INDENT INDENT x INDENT compute 'x ; at this point, stack is (0 2 ? ?) ; again, first indent below is "real" indent" INDENT y INDENT compute 'y ; at this point, stack is (0 2 ? ? 4 ?) ; since we get back to an indent of 2, ; emit 2 DEDENT's to get past the 4, ; then (via rule 5.1) pop off all ? to ; reach the 2 (which involves popping ; off 4 indents). DEDENT DEDENT DEDENT DEDENT use x y ; again, empty line, pop off the single dedent DEDENT ==> let !\\ !!\\ !!!x !!!!compute 'x !!!!!y !!!!!!compute 'y ..... well, bummer, doesn't work. Oh well. Sincerely, AmkG > > A common objection to any scheme allowing unmatched dedents is that it > requires lookahead, both for machine parsing *and humans*. When you read: > > foo > ! ! bar > ... pages of stuff > ! ! baz > ! quux > > it's very disconcerting to realize that all this bar...baz stuff was not a > direct child of foo but was nested within a ...quux construct! > But in our case, $ already declares that we opened an inner construct, so I > think it won't be surprising to humans. > > What about multiple $ ambiguity? Given: > > A1 $ B1 $ C1 > ! ! C2 > ! B2 > > why does the dedent return you to the inner B level and not the outer A > level? > It's the only sane choice, for several reasons: > - Continuity with current usage, which I expect will remain the dominant > use of $: without unmatched dedents you only have access to innermost C > level, so the accessible level should be the next innermost. > - It's the only way (without magic lookahead) that allows you to access all > levels, if desired. > - It's similar to the standard resolution of "if A1 if B1 if C1 else C2 > else B2". > ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ Readable-discuss mailing list Readable-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/readable-discuss