Arne Babenhauserheide | 9 Jun 2012 13:04
Picon
Gravatar

Re: Arne Babenhauserheide proposal: use "." on own line instead of "group"

Hi,

At Wed, 23 May 2012 12:54:18 -0400 (EDT),
David A Wheeler wrote:
> 
> Alpheus Madsen <alpheus.madsen <at> gmail.com>
> > One thought I've been wanting to experiment with, but haven't had the time to attempt to implement, is to
use a double-indent to indicate groups.
> 
> I think that's even worse.  It's very unreadable.  It's also ambiguous for the first indent; does "two
spaces" mean an indent of two spaces, or a double-indent for one-space indenting?

Using double indent had also been my first idea, but I discarded it, because the meaning of the double indent
would not be obvious without the less-indented line which comes later - it would be ambigous.

example:

(let 
     ((a b)(c d)) 
   (e))

becomes

let
    a b
    c d
  e

Imagine 5 let arguments and you cannot know anymore if it’s double-indented.

(Continue reading)

Alan Manuel Gloria | 29 Jun 2012 16:28
Picon
Gravatar

Re: Proposed update and expansion of SRFI-49 (I-expressions) - indented s-expressions

Currently planning on implementing a hardware description language in Guile, and realized that I've been spoiled on Haskell for so long that I find looking at Scheme code gives me headaches.  This now makes sweet-expressions a high priority for me.

So I propose the following parser for sweet expressions.  Note that it's more like a combinator parser with binding; it's declarative, of a sort, but is no longer just BNF.  This lets us avoid describing INDENT and DEDENT using plain English, and thus avoid some classes of ambiguities.

This is sweet-expressions, not I-expressions, so I also integrate modern-expressions and curly-infix.

; ignore completely empty lines
swt-expr -> empty-line* swt-expr-core
  $2

; some simple utility parsers
empty-line -> htspace* eol
htspace -> SPACE | TAB | FORMFEED | VTAB | comment
comment -> COMMENT-MARKER (not eol)*
eol -> CR | LF
; tabs are disallowed currently
; we could define a preprocessor
; that expands tabs.
; FORMFEED and VTAB are
; not always represented as
; single characters either; e.g.
; vim uses ^n form
; for those.
hspace -> SPACE

; for exact number of spaces
(spaces 1) -> SPACE
(spaces n) -> SPACE (spaces (- n 1))

; implements "whitespace at top-level
; DISABLES I-expressions"
swt-expr-core -> htspace+ mdn-expr
  $2
; I-expressions must start at
; indent 0.  Sorry dwheeler.
; Most consistent seems
; too complex or has other
; problems.
swt-expr-core -> (i-expr 0)
  $1

; ignore splice at start of i-expr
; this handles splice
; at start of line.
(i-expr lvl) -> SPLICE hspace* (i-expr lvl)
  $3

; implements dwheeler's spec fix.
(i-expr lvl) -> QUOTE hspace+ (i-expr lvl)
  (list 'quote $3)
(i-expr lvl) -> QUASIQUOTE hspace+ (i-expr lvl)
  (list 'quasiquote $3)
(i-expr lvl) -> UNQUOTE hspace+ (i-expr lvl)
  (list 'unquote $3)
(i-expr lvl) -> UNQUOTE-SPLICING hspace+ (i-expr lvl)
  (list 'unquote-splicing $3)
; NB: because of the hspace requirement,
; implementing the above means that we
; must take over some of mdn-expr's
; work; if after finding QUOTE et al.
; we DON'T find hspace, recurse into
; mdn-expr and add to the current head.

(i-expr lvl) -> GROUP head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $2 $4)
(i-expr lvl) -> GROUP eol-empty-lines (body inlvl), if (> inlvl lvl)
  $3
(i-expr lvl) -> GROUP head eol-empty-lines
  (if (= (length $2) 1)
      (car $2)
      $2)
(i-expr lvl) -> head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $1 $3)
(i-expr lvl) -> head eol-empty-lines
  (if (= (length $1) 1)
      (car $1)
      $1)

; another simple utility parser
eol-empty-lines -> htspace* eol empty-line*

; head handles part of the new
; "splice" concept.
head -> mdn-expr SPLICE eol-empty-lines htspace* head
  (cons $1 $5)
head -> mdn-expr hspace* head
  (cons $1 $3)
head -> mdn-expr
  (list $1)

; body handles the final part of the
; new "splice" concept, viz., splice
; on same line
(body lvl) -> (spaces lvl) (sub-body lvl)
  $2
(body lvl) -> ; empty
  '()

(sub-body lvl) -> (i-expr lvl) hspace* SPLICE hspace* (sub-body lvl)
  (cons $1 $5)
(sub-body lvl) -> (i-expr lvl) eol-empty-lines (body lvl)
  (cons $1 $3)

----

Final notes:

The above seems non-implementable for the SPLICE case of head, actually.  Consider that a comment, or a bunch of invisible space characters, may occur after a SPLICE character.  We must scan past those characters to differentiate between the SPLICE-in-the-middle and SPLICE-at-the-end.  Consider a top-level like this:

define foo bar \ define x 0 \ define answer 42

The above should fail head's SPLICE case, but we can't implement that with only one-character-readahead!  By the time we see the "d", we've already consumed some whitespace.

Proposal:
1.  Remove the SPLICE-at-the-end rule!  It can't be implemented except in the very narrow case that a very very very literal newline exists exactly after it.  Modern compilers like GCC will scan ahead if it finds a space or tab after a "\", because they (wisely) consider the possibility that the programmer might have inadvertently put a space or tab after the backslash and before the newline.  But with only one-character-readahead it's just not possible.

---

Another comment:

re: "the sample code isn't obviously related to the BNF" is mostly because the terminal GROUP is composed of multiple characters, and we have only one-character-readahead (pretty much all the other terminals are single characters: CR, LF, SPACE, TAB, VTAB, FORMFEED... only UNQUOTE-SPLICING isn't, and we can just fudge up the UNQUOTE rule for that...).  If GROUP is instead "." as proposed by Arne, we might actually be able to code closer to the parser declarative spec.  Overloading "\" for both GROUP and SPLICE may require some more thinking, especially with the interaction of SPLICE and top-level declarations (such as the top-level "define foo bar \ define x 0 \ define answer 42" case given.  My initial instinct is that "%s/GROUP/SPLICE/g" won't actually have any negative effects, though, so \ might be usefully overloaded as both SPLICE and GROUP.

On Tue, Jan 1, 2008 at 10:42 PM, David A. Wheeler <dwheeler-OyCmK+MLziRWk0Htik3J/w@public.gmane.org> wrote:
SRFI-49 (http://srfi.schemers.org/srfi-49/srfi-49.html) provides a
pretty good system for indentation, but there are some issues.
The spec has a few errors, and the BNF productions don't include much
information on the whitespace-handling (which may explain why the sample
implementation has a bug in handling comments in certain constructs).
In addition, the sample code isn't obviously related to the BNF productions,
so it's hard to say that the code is correct.

So, below are step-by-step transforms of the
SRFI-49 rules.  The first one is a mild "fix-up" of the SFRI rules;
the second takes the first and adds whitespace rules that are
(mostly) implicit in the text, as well as proposing a way to deal
with "initial indent".

It may be easier to simply re-implement the spec, given the details,
so that we can be more confident that the final code is correct.

Of course, that presumes that the below is actually CORRECT.  Comments? Thoughts?

===========================================================
Here are the productions from SRFI-49, with these fixes/changes:
(1) the "head" productions' "expr" are changed to "s-expr" (a spec bug),
(2) the rule for "head-> s-expr" is changed from "(list expr)" to
   "(list $1)" (a spec bug),
(3) the missing rule for UNQUOTE-SPLICING has been added (spec bug),
(4) they are reordered so the GROUP productions are adjacent.
(5) Notice that

 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE expr
  (list 'quote $2)
 expr -> QUASIQUOTE expr
  (list 'quasiquote $2)
 expr -> UNQUOTE expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING expr  ; , <at>
  (list 'unquote-splicing $2)

 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 head-> s-expr head
  (append $1 $2)
 head-> s-expr
  (list $1)

 body -> expr body
   (cons $1 $2)
 body ->
  '()


===========================================================
Detailed version of spec

The original spec described in _words_ what to do about whitespace;
let's make that more explicit.  We can do this by modifying the
whitespace preprocessor's description slightly; it will output
SPACE or TAB if not at beginning of line, and at the end of each line
it will report NL (newline) or EOF (end of file).  It will NOT consume
comments (beginning with ";" through EOL).  It will still notice
the beginning of a line (start of reading, or after NL),
and conceptually output INDENT or DEDENT as appropriate after NL
(if it outputs neither after NL, we're on the SAME indentation level).
EOF can start a whole new expression, but can't be in the middle of one
(so  ' <EOF> is not legal).

Proposal: Treat as line with only horizontal whitespace as if it's
a line solely with newline - i.e., as if the horizontal whitespace
didn't even exist.  After all, you can't see the difference when printing,
and typically can't see them when editing either.
This appears to be the safer alternative.


get-leading-hspace:
  sequence <- get sequence of spaces and tabs
  if memv(peek() '(NL EOF))
     ""  ; if whitespace followed by newline (no ;), treat as newline-by-self
     sequence

Here's the state machine of the whitespace processor, described
in pseudocode using sweet-expressions 0.2:

Start:
 {newstate <- Leftedge}
 push("")
Left-edge:
 {new-indent <- get-leading-hspace()}
 {newstate <- process-edge}
Process-edge:
 cond
   {new-indent > peek()}  {newstate <- Normal} push(new-indent) return(INDENT)
   {new-indent = peek()}  {newstate <- Normal}
   {new-indent < peek()}  {newstate <- Process-edge} pop() return(DEDENT)
   else error("Incomparable indents")
Normal:
 {c <- get-char()}
 if memv(c '(NL EOF))
   {newstate <- Left-edge}
 return(c)


The state machine need not be IMPLEMENTED this way.
Characters can be peeked, then used there if they aren't NL/EOF;
if they are NL/EOF then call to find the new line's indent.
Pass down to routines the string with "current line's indent", and return
(current-line-indent result)... procedure returns can be the
equivalent of DEDENT processing, and procedure calls the equivalent
of INDENT processing.  But it's easier to DESCRIBE this way.



 ; Definitions of whitespace:
 eol -> comment? eol-final               ; eol = "end of line"
 comment -> ";" (not NL|EOF)*   ; Note: does not consume NL or EOF.
 eol-final -> NL | EOF
 hspace -> SPACE | TAB


 ; Clarify - start-up is slightly special (esp. EOF).
 start-expr -> expr
   $1
 start-expr -> EOF
   $1
 start-expr -> eol start-expr ; Skip initial blank/comment-only lines
   $2
 start-expr -> INDENT eol start-expr DEDENT ; Skip indented comment-only lines
   $2

 ; Let's use the "most consistent" option for handling indents at toplevel;
 ; see below for more about the various options:
 start-expr -> INDENT expr DEDENT


 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE hspace* expr
  (list 'quote $2)
 expr -> QUASIQUOTE hspace* expr
  (list 'quasiquote $2)
 expr -> UNQUOTE hspace* expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING hspace* expr  ; , <at>
  (list 'unquote-splicing $2)

 ; In actual code, you can't tell between GROUP and head until an
 ; s-expr is read in.  So in the implementation, read in an s-expr,
 ; then look at the s-expr to see if it's "group" or not.
 ; Note: Some of the hspace* below create "ambiguities" that don't matter.
 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP hspace* INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 ; "head" is what happens on ONE line, and a head sequence ends with eol.
 ; Note: the hspace* below are lower-precedence than the hspace used for
 ; INDENT/DEDENT, and won't consume characters for a line's first term...
 ; but it's much easier to express the hspace* consuming here than to
 ; sprinkle it elsewhere.
 head -> hspace* s-expr hspace+ head ; hspace+ can be read with hspace*
  (append $1 $3)
 head -> hspace* s-expr hspace* eol
  (list $1)

 ; "body" is the set of children lines (from the point-of-view of head)
 body -> expr body
   (cons $1 $2)
 body ->
  '()       ; No more children
 body -> comment eol-final body
  $2        ; Skip comment lines with the same indentation

 ; s-expr is a traditional s-expr, aka datum.  It does NOT begin with ";",
 ; hspace, NL, or EOF.  To implement it, the I-expression reader calls
 ; the _previous_ reader of datum.
 ; When processing "expr", the special definitions for
 ; abbreviations QUOTE etc. take precedence; but if you're processing
 ; the later entries of "head" (i.e., datums that are NOT the first
 ; datum on the line), the s-expr reader must handle the abbreviations.

 ; Note: I-expressions do not provide special syntax for improper lists,
 ; e.g., (a . b).  When you need them, just use s-expressions or cons.
 ; A _syntax_ for this would be easy, e.g., rules like:
 ;   head -> s-expr hspace+ "." hspace+ s-expr
 ; However, it'd be hard to IMPLEMENT, because "." is a leading character
 ; for many different circumstances (.9, ..., etc.), yet calling the
 ; underlying reader might not be effective.  E.G., clisp's "read" will
 ; fail if given a solo ".".  Since you can use s-expressions or cons
 ; to construct these, there doesn't seem to be a compelling need for such
 ; a special syntax in I-expressions, anyway... especially given
 ; their implementation headaches.


--- David A. Wheeler

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Readable-discuss mailing list
Readable-discuss <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 29 Jun 2012 17:39
Picon
Gravatar

Re: Proposed update and expansion of SRFI-49 (I-expressions) - indented s-expressions

Here's mdn-expr:

; LPAREN/RPAREN = ()
; LBRACKET/RBRACKET = []
; LBRACE/RBRACE = {}

; prefixed cases
mdn-expr -> base-expr post-mdn-expr
  ($2 $1)
mdn-expr -> base-expr
  $1

; valid suffix forms () [] {}
post-mdn-expr -> post-mdn-expr-1
  $1
post-mdn-expr -> post-mdn-expr-1 post-mdn-expr
  (lambda (e) ($2 ($1)))

post-mdn-expr-1 -> LBRACKET mdn-expr* RBRACKET
  ; assuming x* yields a list, possibly empty
  (lambda (e) (cons 'bracketaccess (cons e $2)))
post-mdn-expr-1 -> curly-infix
  (lambda (e) (list e $1))
post-mdn-expr-1 -> LPAREN mdn-expr* RPAREN
  (lambda (e) (cons e $2))

base-expr -> LPAREN htspace* mdn-expr-spaced* RPAREN
  $3
base-expr -> bracket-notation
  $1
base-expr -> curly-infix
  $1
base-expr -> ATOM ; where ATOM is string, symbol, number, #foo, etc.
  $1

; varies based on exact Lisp being used.
bracket-notation -> bracket-notation-scheme
  $1
;; bracket-notation -> bracket-notation-arc
;;   $1
bracket-notation-scheme -> LBRACKET htspace* mdn-expr-spaced* RBRACKET
  $3
bracket-notation-arc -> LBRACKET htspace* mdn-expr-spaced* RBRACKET
  (list 'fn (list '_) $3)

mdn-expr-spaced -> mdn-expr htspace*
  $1

---

For curly-infix, we can't actually use the above syntax to express it, at least not if we want to support {a + b + c} form.  But it's possible to write it out, and it's quite simple; we don't describe it here anymore.

On Fri, Jun 29, 2012 at 10:28 PM, Alan Manuel Gloria <almkglor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Currently planning on implementing a hardware description language in Guile, and realized that I've been spoiled on Haskell for so long that I find looking at Scheme code gives me headaches.  This now makes sweet-expressions a high priority for me.

So I propose the following parser for sweet expressions.  Note that it's more like a combinator parser with binding; it's declarative, of a sort, but is no longer just BNF.  This lets us avoid describing INDENT and DEDENT using plain English, and thus avoid some classes of ambiguities.

This is sweet-expressions, not I-expressions, so I also integrate modern-expressions and curly-infix.

; ignore completely empty lines
swt-expr -> empty-line* swt-expr-core
  $2

; some simple utility parsers
empty-line -> htspace* eol
htspace -> SPACE | TAB | FORMFEED | VTAB | comment
comment -> COMMENT-MARKER (not eol)*
eol -> CR | LF
; tabs are disallowed currently
; we could define a preprocessor
; that expands tabs.
; FORMFEED and VTAB are
; not always represented as
; single characters either; e.g.
; vim uses ^n form
; for those.
hspace -> SPACE

; for exact number of spaces
(spaces 1) -> SPACE
(spaces n) -> SPACE (spaces (- n 1))

; implements "whitespace at top-level
; DISABLES I-expressions"
swt-expr-core -> htspace+ mdn-expr
  $2
; I-expressions must start at
; indent 0.  Sorry dwheeler.
; Most consistent seems
; too complex or has other
; problems.
swt-expr-core -> (i-expr 0)
  $1

; ignore splice at start of i-expr
; this handles splice
; at start of line.
(i-expr lvl) -> SPLICE hspace* (i-expr lvl)
  $3

; implements dwheeler's spec fix.
(i-expr lvl) -> QUOTE hspace+ (i-expr lvl)
  (list 'quote $3)
(i-expr lvl) -> QUASIQUOTE hspace+ (i-expr lvl)
  (list 'quasiquote $3)
(i-expr lvl) -> UNQUOTE hspace+ (i-expr lvl)
  (list 'unquote $3)
(i-expr lvl) -> UNQUOTE-SPLICING hspace+ (i-expr lvl)
  (list 'unquote-splicing $3)
; NB: because of the hspace requirement,
; implementing the above means that we
; must take over some of mdn-expr's
; work; if after finding QUOTE et al.
; we DON'T find hspace, recurse into
; mdn-expr and add to the current head.

(i-expr lvl) -> GROUP head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $2 $4)
(i-expr lvl) -> GROUP eol-empty-lines (body inlvl), if (> inlvl lvl)
  $3
(i-expr lvl) -> GROUP head eol-empty-lines

  (if (= (length $2) 1)
      (car $2)
      $2)
(i-expr lvl) -> head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $1 $3)
(i-expr lvl) -> head eol-empty-lines

  (if (= (length $1) 1)
      (car $1)
      $1)

; another simple utility parser
eol-empty-lines -> htspace* eol empty-line*

; head handles part of the new
; "splice" concept.
head -> mdn-expr SPLICE eol-empty-lines htspace* head
  (cons $1 $5)
head -> mdn-expr hspace* head
  (cons $1 $3)
head -> mdn-expr
  (list $1)

; body handles the final part of the
; new "splice" concept, viz., splice
; on same line
(body lvl) -> (spaces lvl) (sub-body lvl)
  $2
(body lvl) -> ; empty
  '()

(sub-body lvl) -> (i-expr lvl) hspace* SPLICE hspace* (sub-body lvl)
  (cons $1 $5)
(sub-body lvl) -> (i-expr lvl) eol-empty-lines (body lvl)
  (cons $1 $3)

----

Final notes:

The above seems non-implementable for the SPLICE case of head, actually.  Consider that a comment, or a bunch of invisible space characters, may occur after a SPLICE character.  We must scan past those characters to differentiate between the SPLICE-in-the-middle and SPLICE-at-the-end.  Consider a top-level like this:

define foo bar \ define x 0 \ define answer 42

The above should fail head's SPLICE case, but we can't implement that with only one-character-readahead!  By the time we see the "d", we've already consumed some whitespace.

Proposal:
1.  Remove the SPLICE-at-the-end rule!  It can't be implemented except in the very narrow case that a very very very literal newline exists exactly after it.  Modern compilers like GCC will scan ahead if it finds a space or tab after a "\", because they (wisely) consider the possibility that the programmer might have inadvertently put a space or tab after the backslash and before the newline.  But with only one-character-readahead it's just not possible.

---

Another comment:

re: "the sample code isn't obviously related to the BNF" is mostly because the terminal GROUP is composed of multiple characters, and we have only one-character-readahead (pretty much all the other terminals are single characters: CR, LF, SPACE, TAB, VTAB, FORMFEED... only UNQUOTE-SPLICING isn't, and we can just fudge up the UNQUOTE rule for that...).  If GROUP is instead "." as proposed by Arne, we might actually be able to code closer to the parser declarative spec.  Overloading "\" for both GROUP and SPLICE may require some more thinking, especially with the interaction of SPLICE and top-level declarations (such as the top-level "define foo bar \ define x 0 \ define answer 42" case given.  My initial instinct is that "%s/GROUP/SPLICE/g" won't actually have any negative effects, though, so \ might be usefully overloaded as both SPLICE and GROUP.


On Tue, Jan 1, 2008 at 10:42 PM, David A. Wheeler <dwheeler-OyCmK+MLziRWk0Htik3J/w@public.gmane.org> wrote:
SRFI-49 (http://srfi.schemers.org/srfi-49/srfi-49.html) provides a
pretty good system for indentation, but there are some issues.
The spec has a few errors, and the BNF productions don't include much
information on the whitespace-handling (which may explain why the sample
implementation has a bug in handling comments in certain constructs).
In addition, the sample code isn't obviously related to the BNF productions,
so it's hard to say that the code is correct.

So, below are step-by-step transforms of the
SRFI-49 rules.  The first one is a mild "fix-up" of the SFRI rules;
the second takes the first and adds whitespace rules that are
(mostly) implicit in the text, as well as proposing a way to deal
with "initial indent".

It may be easier to simply re-implement the spec, given the details,
so that we can be more confident that the final code is correct.

Of course, that presumes that the below is actually CORRECT.  Comments? Thoughts?

===========================================================
Here are the productions from SRFI-49, with these fixes/changes:
(1) the "head" productions' "expr" are changed to "s-expr" (a spec bug),
(2) the rule for "head-> s-expr" is changed from "(list expr)" to
   "(list $1)" (a spec bug),
(3) the missing rule for UNQUOTE-SPLICING has been added (spec bug),
(4) they are reordered so the GROUP productions are adjacent.
(5) Notice that

 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE expr
  (list 'quote $2)
 expr -> QUASIQUOTE expr
  (list 'quasiquote $2)
 expr -> UNQUOTE expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING expr  ; , <at>
  (list 'unquote-splicing $2)

 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 head-> s-expr head
  (append $1 $2)
 head-> s-expr
  (list $1)

 body -> expr body
   (cons $1 $2)
 body ->
  '()


===========================================================
Detailed version of spec

The original spec described in _words_ what to do about whitespace;
let's make that more explicit.  We can do this by modifying the
whitespace preprocessor's description slightly; it will output
SPACE or TAB if not at beginning of line, and at the end of each line
it will report NL (newline) or EOF (end of file).  It will NOT consume
comments (beginning with ";" through EOL).  It will still notice
the beginning of a line (start of reading, or after NL),
and conceptually output INDENT or DEDENT as appropriate after NL
(if it outputs neither after NL, we're on the SAME indentation level).
EOF can start a whole new expression, but can't be in the middle of one
(so  ' <EOF> is not legal).

Proposal: Treat as line with only horizontal whitespace as if it's
a line solely with newline - i.e., as if the horizontal whitespace
didn't even exist.  After all, you can't see the difference when printing,
and typically can't see them when editing either.
This appears to be the safer alternative.


get-leading-hspace:
  sequence <- get sequence of spaces and tabs
  if memv(peek() '(NL EOF))
     ""  ; if whitespace followed by newline (no ;), treat as newline-by-self
     sequence

Here's the state machine of the whitespace processor, described
in pseudocode using sweet-expressions 0.2:

Start:
 {newstate <- Leftedge}
 push("")
Left-edge:
 {new-indent <- get-leading-hspace()}
 {newstate <- process-edge}
Process-edge:
 cond
   {new-indent > peek()}  {newstate <- Normal} push(new-indent) return(INDENT)
   {new-indent = peek()}  {newstate <- Normal}
   {new-indent < peek()}  {newstate <- Process-edge} pop() return(DEDENT)
   else error("Incomparable indents")
Normal:
 {c <- get-char()}
 if memv(c '(NL EOF))
   {newstate <- Left-edge}
 return(c)


The state machine need not be IMPLEMENTED this way.
Characters can be peeked, then used there if they aren't NL/EOF;
if they are NL/EOF then call to find the new line's indent.
Pass down to routines the string with "current line's indent", and return
(current-line-indent result)... procedure returns can be the
equivalent of DEDENT processing, and procedure calls the equivalent
of INDENT processing.  But it's easier to DESCRIBE this way.



 ; Definitions of whitespace:
 eol -> comment? eol-final               ; eol = "end of line"
 comment -> ";" (not NL|EOF)*   ; Note: does not consume NL or EOF.
 eol-final -> NL | EOF
 hspace -> SPACE | TAB


 ; Clarify - start-up is slightly special (esp. EOF).
 start-expr -> expr
   $1
 start-expr -> EOF
   $1
 start-expr -> eol start-expr ; Skip initial blank/comment-only lines
   $2
 start-expr -> INDENT eol start-expr DEDENT ; Skip indented comment-only lines
   $2

 ; Let's use the "most consistent" option for handling indents at toplevel;
 ; see below for more about the various options:
 start-expr -> INDENT expr DEDENT


 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE hspace* expr
  (list 'quote $2)
 expr -> QUASIQUOTE hspace* expr
  (list 'quasiquote $2)
 expr -> UNQUOTE hspace* expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING hspace* expr  ; , <at>
  (list 'unquote-splicing $2)

 ; In actual code, you can't tell between GROUP and head until an
 ; s-expr is read in.  So in the implementation, read in an s-expr,
 ; then look at the s-expr to see if it's "group" or not.
 ; Note: Some of the hspace* below create "ambiguities" that don't matter.
 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP hspace* INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 ; "head" is what happens on ONE line, and a head sequence ends with eol.
 ; Note: the hspace* below are lower-precedence than the hspace used for
 ; INDENT/DEDENT, and won't consume characters for a line's first term...
 ; but it's much easier to express the hspace* consuming here than to
 ; sprinkle it elsewhere.
 head -> hspace* s-expr hspace+ head ; hspace+ can be read with hspace*
  (append $1 $3)
 head -> hspace* s-expr hspace* eol
  (list $1)

 ; "body" is the set of children lines (from the point-of-view of head)
 body -> expr body
   (cons $1 $2)
 body ->
  '()       ; No more children
 body -> comment eol-final body
  $2        ; Skip comment lines with the same indentation

 ; s-expr is a traditional s-expr, aka datum.  It does NOT begin with ";",
 ; hspace, NL, or EOF.  To implement it, the I-expression reader calls
 ; the _previous_ reader of datum.
 ; When processing "expr", the special definitions for
 ; abbreviations QUOTE etc. take precedence; but if you're processing
 ; the later entries of "head" (i.e., datums that are NOT the first
 ; datum on the line), the s-expr reader must handle the abbreviations.

 ; Note: I-expressions do not provide special syntax for improper lists,
 ; e.g., (a . b).  When you need them, just use s-expressions or cons.
 ; A _syntax_ for this would be easy, e.g., rules like:
 ;   head -> s-expr hspace+ "." hspace+ s-expr
 ; However, it'd be hard to IMPLEMENT, because "." is a leading character
 ; for many different circumstances (.9, ..., etc.), yet calling the
 ; underlying reader might not be effective.  E.G., clisp's "read" will
 ; fail if given a solo ".".  Since you can use s-expressions or cons
 ; to construct these, there doesn't seem to be a compelling need for such
 ; a special syntax in I-expressions, anyway... especially given
 ; their implementation headaches.


--- David A. Wheeler

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Readable-discuss mailing list
Readable-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/readable-discuss


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 29 Jun 2012 17:43
Picon
Gravatar

Re: Proposed update and expansion of SRFI-49 (I-expressions) - indented s-expressions

Argh darn it, I realized that mdn-expr needs quote syntax!

please change these lines:

; prefixed cases
mdn-expr -> base-expr post-mdn-expr
  ($2 $1)
mdn-expr -> base-expr
  $1

to:

; prefixed cases
mdn-expr-post-q -> base-expr post-mdn-expr
  ($2 $1)
mdn-expr-post-q -> base-expr
  $1

And add:

mdn-expr -> QUOTE htspace* mdn-expr
  (list 'quote $3)
mdn-expr -> QUASIQUOTE htspace* mdn-expr
  (list 'quasiquote $3)
mdn-expr -> UNQUOTE htspace* mdn-expr
  (list 'unquote $3)
mdn-expr -> UNQUOTE-SPLICING htpsace* mdn-expr
  (list 'unquote-splicing $3)
mdn-expr -> mdn-expr-post-q
  $1


On Fri, Jun 29, 2012 at 11:39 PM, Alan Manuel Gloria <almkglor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Here's mdn-expr:

; LPAREN/RPAREN = ()
; LBRACKET/RBRACKET = []
; LBRACE/RBRACE = {}

; prefixed cases
mdn-expr -> base-expr post-mdn-expr
  ($2 $1)
mdn-expr -> base-expr
  $1

; valid suffix forms () [] {}
post-mdn-expr -> post-mdn-expr-1
  $1
post-mdn-expr -> post-mdn-expr-1 post-mdn-expr
  (lambda (e) ($2 ($1)))

post-mdn-expr-1 -> LBRACKET mdn-expr* RBRACKET
  ; assuming x* yields a list, possibly empty
  (lambda (e) (cons 'bracketaccess (cons e $2)))
post-mdn-expr-1 -> curly-infix
  (lambda (e) (list e $1))
post-mdn-expr-1 -> LPAREN mdn-expr* RPAREN
  (lambda (e) (cons e $2))

base-expr -> LPAREN htspace* mdn-expr-spaced* RPAREN
  $3
base-expr -> bracket-notation
  $1
base-expr -> curly-infix
  $1
base-expr -> ATOM ; where ATOM is string, symbol, number, #foo, etc.
  $1

; varies based on exact Lisp being used.
bracket-notation -> bracket-notation-scheme
  $1
;; bracket-notation -> bracket-notation-arc
;;   $1
bracket-notation-scheme -> LBRACKET htspace* mdn-expr-spaced* RBRACKET
  $3
bracket-notation-arc -> LBRACKET htspace* mdn-expr-spaced* RBRACKET
  (list 'fn (list '_) $3)

mdn-expr-spaced -> mdn-expr htspace*
  $1

---

For curly-infix, we can't actually use the above syntax to express it, at least not if we want to support {a + b + c} form.  But it's possible to write it out, and it's quite simple; we don't describe it here anymore.


On Fri, Jun 29, 2012 at 10:28 PM, Alan Manuel Gloria <almkglor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Currently planning on implementing a hardware description language in Guile, and realized that I've been spoiled on Haskell for so long that I find looking at Scheme code gives me headaches.  This now makes sweet-expressions a high priority for me.

So I propose the following parser for sweet expressions.  Note that it's more like a combinator parser with binding; it's declarative, of a sort, but is no longer just BNF.  This lets us avoid describing INDENT and DEDENT using plain English, and thus avoid some classes of ambiguities.

This is sweet-expressions, not I-expressions, so I also integrate modern-expressions and curly-infix.

; ignore completely empty lines
swt-expr -> empty-line* swt-expr-core
  $2

; some simple utility parsers
empty-line -> htspace* eol
htspace -> SPACE | TAB | FORMFEED | VTAB | comment
comment -> COMMENT-MARKER (not eol)*
eol -> CR | LF
; tabs are disallowed currently
; we could define a preprocessor
; that expands tabs.
; FORMFEED and VTAB are
; not always represented as
; single characters either; e.g.
; vim uses ^n form
; for those.
hspace -> SPACE

; for exact number of spaces
(spaces 1) -> SPACE
(spaces n) -> SPACE (spaces (- n 1))

; implements "whitespace at top-level
; DISABLES I-expressions"
swt-expr-core -> htspace+ mdn-expr
  $2
; I-expressions must start at
; indent 0.  Sorry dwheeler.
; Most consistent seems
; too complex or has other
; problems.
swt-expr-core -> (i-expr 0)
  $1

; ignore splice at start of i-expr
; this handles splice
; at start of line.
(i-expr lvl) -> SPLICE hspace* (i-expr lvl)
  $3

; implements dwheeler's spec fix.
(i-expr lvl) -> QUOTE hspace+ (i-expr lvl)
  (list 'quote $3)
(i-expr lvl) -> QUASIQUOTE hspace+ (i-expr lvl)
  (list 'quasiquote $3)
(i-expr lvl) -> UNQUOTE hspace+ (i-expr lvl)
  (list 'unquote $3)
(i-expr lvl) -> UNQUOTE-SPLICING hspace+ (i-expr lvl)
  (list 'unquote-splicing $3)
; NB: because of the hspace requirement,
; implementing the above means that we
; must take over some of mdn-expr's
; work; if after finding QUOTE et al.
; we DON'T find hspace, recurse into
; mdn-expr and add to the current head.

(i-expr lvl) -> GROUP head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $2 $4)
(i-expr lvl) -> GROUP eol-empty-lines (body inlvl), if (> inlvl lvl)
  $3
(i-expr lvl) -> GROUP head eol-empty-lines

  (if (= (length $2) 1)
      (car $2)
      $2)
(i-expr lvl) -> head eol-empty-lines (body inlvl), if (> inlvl lvl)
  (append $1 $3)
(i-expr lvl) -> head eol-empty-lines

  (if (= (length $1) 1)
      (car $1)
      $1)

; another simple utility parser
eol-empty-lines -> htspace* eol empty-line*

; head handles part of the new
; "splice" concept.
head -> mdn-expr SPLICE eol-empty-lines htspace* head
  (cons $1 $5)
head -> mdn-expr hspace* head
  (cons $1 $3)
head -> mdn-expr
  (list $1)

; body handles the final part of the
; new "splice" concept, viz., splice
; on same line
(body lvl) -> (spaces lvl) (sub-body lvl)
  $2
(body lvl) -> ; empty
  '()

(sub-body lvl) -> (i-expr lvl) hspace* SPLICE hspace* (sub-body lvl)
  (cons $1 $5)
(sub-body lvl) -> (i-expr lvl) eol-empty-lines (body lvl)
  (cons $1 $3)

----

Final notes:

The above seems non-implementable for the SPLICE case of head, actually.  Consider that a comment, or a bunch of invisible space characters, may occur after a SPLICE character.  We must scan past those characters to differentiate between the SPLICE-in-the-middle and SPLICE-at-the-end.  Consider a top-level like this:

define foo bar \ define x 0 \ define answer 42

The above should fail head's SPLICE case, but we can't implement that with only one-character-readahead!  By the time we see the "d", we've already consumed some whitespace.

Proposal:
1.  Remove the SPLICE-at-the-end rule!  It can't be implemented except in the very narrow case that a very very very literal newline exists exactly after it.  Modern compilers like GCC will scan ahead if it finds a space or tab after a "\", because they (wisely) consider the possibility that the programmer might have inadvertently put a space or tab after the backslash and before the newline.  But with only one-character-readahead it's just not possible.

---

Another comment:

re: "the sample code isn't obviously related to the BNF" is mostly because the terminal GROUP is composed of multiple characters, and we have only one-character-readahead (pretty much all the other terminals are single characters: CR, LF, SPACE, TAB, VTAB, FORMFEED... only UNQUOTE-SPLICING isn't, and we can just fudge up the UNQUOTE rule for that...).  If GROUP is instead "." as proposed by Arne, we might actually be able to code closer to the parser declarative spec.  Overloading "\" for both GROUP and SPLICE may require some more thinking, especially with the interaction of SPLICE and top-level declarations (such as the top-level "define foo bar \ define x 0 \ define answer 42" case given.  My initial instinct is that "%s/GROUP/SPLICE/g" won't actually have any negative effects, though, so \ might be usefully overloaded as both SPLICE and GROUP.


On Tue, Jan 1, 2008 at 10:42 PM, David A. Wheeler <dwheeler-OyCmK+MLziRWk0Htik3J/w@public.gmane.org> wrote:
SRFI-49 (http://srfi.schemers.org/srfi-49/srfi-49.html) provides a
pretty good system for indentation, but there are some issues.
The spec has a few errors, and the BNF productions don't include much
information on the whitespace-handling (which may explain why the sample
implementation has a bug in handling comments in certain constructs).
In addition, the sample code isn't obviously related to the BNF productions,
so it's hard to say that the code is correct.

So, below are step-by-step transforms of the
SRFI-49 rules.  The first one is a mild "fix-up" of the SFRI rules;
the second takes the first and adds whitespace rules that are
(mostly) implicit in the text, as well as proposing a way to deal
with "initial indent".

It may be easier to simply re-implement the spec, given the details,
so that we can be more confident that the final code is correct.

Of course, that presumes that the below is actually CORRECT.  Comments? Thoughts?

===========================================================
Here are the productions from SRFI-49, with these fixes/changes:
(1) the "head" productions' "expr" are changed to "s-expr" (a spec bug),
(2) the rule for "head-> s-expr" is changed from "(list expr)" to
   "(list $1)" (a spec bug),
(3) the missing rule for UNQUOTE-SPLICING has been added (spec bug),
(4) they are reordered so the GROUP productions are adjacent.
(5) Notice that

 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE expr
  (list 'quote $2)
 expr -> QUASIQUOTE expr
  (list 'quasiquote $2)
 expr -> UNQUOTE expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING expr  ; , <at>
  (list 'unquote-splicing $2)

 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 head-> s-expr head
  (append $1 $2)
 head-> s-expr
  (list $1)

 body -> expr body
   (cons $1 $2)
 body ->
  '()


===========================================================
Detailed version of spec

The original spec described in _words_ what to do about whitespace;
let's make that more explicit.  We can do this by modifying the
whitespace preprocessor's description slightly; it will output
SPACE or TAB if not at beginning of line, and at the end of each line
it will report NL (newline) or EOF (end of file).  It will NOT consume
comments (beginning with ";" through EOL).  It will still notice
the beginning of a line (start of reading, or after NL),
and conceptually output INDENT or DEDENT as appropriate after NL
(if it outputs neither after NL, we're on the SAME indentation level).
EOF can start a whole new expression, but can't be in the middle of one
(so  ' <EOF> is not legal).

Proposal: Treat as line with only horizontal whitespace as if it's
a line solely with newline - i.e., as if the horizontal whitespace
didn't even exist.  After all, you can't see the difference when printing,
and typically can't see them when editing either.
This appears to be the safer alternative.


get-leading-hspace:
  sequence <- get sequence of spaces and tabs
  if memv(peek() '(NL EOF))
     ""  ; if whitespace followed by newline (no ;), treat as newline-by-self
     sequence

Here's the state machine of the whitespace processor, described
in pseudocode using sweet-expressions 0.2:

Start:
 {newstate <- Leftedge}
 push("")
Left-edge:
 {new-indent <- get-leading-hspace()}
 {newstate <- process-edge}
Process-edge:
 cond
   {new-indent > peek()}  {newstate <- Normal} push(new-indent) return(INDENT)
   {new-indent = peek()}  {newstate <- Normal}
   {new-indent < peek()}  {newstate <- Process-edge} pop() return(DEDENT)
   else error("Incomparable indents")
Normal:
 {c <- get-char()}
 if memv(c '(NL EOF))
   {newstate <- Left-edge}
 return(c)


The state machine need not be IMPLEMENTED this way.
Characters can be peeked, then used there if they aren't NL/EOF;
if they are NL/EOF then call to find the new line's indent.
Pass down to routines the string with "current line's indent", and return
(current-line-indent result)... procedure returns can be the
equivalent of DEDENT processing, and procedure calls the equivalent
of INDENT processing.  But it's easier to DESCRIBE this way.



 ; Definitions of whitespace:
 eol -> comment? eol-final               ; eol = "end of line"
 comment -> ";" (not NL|EOF)*   ; Note: does not consume NL or EOF.
 eol-final -> NL | EOF
 hspace -> SPACE | TAB


 ; Clarify - start-up is slightly special (esp. EOF).
 start-expr -> expr
   $1
 start-expr -> EOF
   $1
 start-expr -> eol start-expr ; Skip initial blank/comment-only lines
   $2
 start-expr -> INDENT eol start-expr DEDENT ; Skip indented comment-only lines
   $2

 ; Let's use the "most consistent" option for handling indents at toplevel;
 ; see below for more about the various options:
 start-expr -> INDENT expr DEDENT


 ; These abbreviations take precedence over processing of s-expr:
 expr -> QUOTE hspace* expr
  (list 'quote $2)
 expr -> QUASIQUOTE hspace* expr
  (list 'quasiquote $2)
 expr -> UNQUOTE hspace* expr
  (list 'unquote $2)
 expr -> UNQUOTE-SPLICING hspace* expr  ; , <at>
  (list 'unquote-splicing $2)

 ; In actual code, you can't tell between GROUP and head until an
 ; s-expr is read in.  So in the implementation, read in an s-expr,
 ; then look at the s-expr to see if it's "group" or not.
 ; Note: Some of the hspace* below create "ambiguities" that don't matter.
 expr -> GROUP head INDENT body DEDENT
  (append $2 $4)
 expr -> GROUP hspace* INDENT body DEDENT
  $3
 expr -> GROUP head
  (if (= (length $2) 1)
      (car $2)
    $2)
 expr -> head INDENT body DEDENT
  (append $1 $3)
 expr -> head
  (if (= (length $1) 1)
      (car $1)
    $1)

 ; "head" is what happens on ONE line, and a head sequence ends with eol.
 ; Note: the hspace* below are lower-precedence than the hspace used for
 ; INDENT/DEDENT, and won't consume characters for a line's first term...
 ; but it's much easier to express the hspace* consuming here than to
 ; sprinkle it elsewhere.
 head -> hspace* s-expr hspace+ head ; hspace+ can be read with hspace*
  (append $1 $3)
 head -> hspace* s-expr hspace* eol
  (list $1)

 ; "body" is the set of children lines (from the point-of-view of head)
 body -> expr body
   (cons $1 $2)
 body ->
  '()       ; No more children
 body -> comment eol-final body
  $2        ; Skip comment lines with the same indentation

 ; s-expr is a traditional s-expr, aka datum.  It does NOT begin with ";",
 ; hspace, NL, or EOF.  To implement it, the I-expression reader calls
 ; the _previous_ reader of datum.
 ; When processing "expr", the special definitions for
 ; abbreviations QUOTE etc. take precedence; but if you're processing
 ; the later entries of "head" (i.e., datums that are NOT the first
 ; datum on the line), the s-expr reader must handle the abbreviations.

 ; Note: I-expressions do not provide special syntax for improper lists,
 ; e.g., (a . b).  When you need them, just use s-expressions or cons.
 ; A _syntax_ for this would be easy, e.g., rules like:
 ;   head -> s-expr hspace+ "." hspace+ s-expr
 ; However, it'd be hard to IMPLEMENT, because "." is a leading character
 ; for many different circumstances (.9, ..., etc.), yet calling the
 ; underlying reader might not be effective.  E.G., clisp's "read" will
 ; fail if given a solo ".".  Since you can use s-expressions or cons
 ; to construct these, there doesn't seem to be a compelling need for such
 ; a special syntax in I-expressions, anyway... especially given
 ; their implementation headaches.


--- David A. Wheeler

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Readable-discuss mailing list
Readable-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/readable-discuss



------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 29 Jun 2012 21:19
Picon
Gravatar

Re: Proposed update and expansion of SRFI-49 (I-expressions) - indented s-expressions

Sigh.  Let me redo mdn-expr

any-space -> SPACE | TAB | VTAB | FORMFEED | CR | LF | comment

; the core implementations here need to be
; factored out, as the sweet-expr parser needs
; to do similar processing when differentating
; between space-significant and space-insignificant
; quote.
mdn-expr -> QUOTE any-space* mdn-expr
  (list 'quote $3)
mdn-expr -> QUASIQUOTE any-space* mdn-expr
  (list 'quasiquote $3)
mdn-expr -> UNQUOTE any-space* mdn-expr
  (list 'unquote $3)
mdn-expr -> UNQUOTE-SPLICING any-space* mdn-expr
  (list 'unquote-splicing $3)
mdn-expr -> mdn-expr-post-quote
  $1

; use a different base-expr here:
; disallow post-mdn-expr after things
; like STRING, NUMBER, OTHER
mdn-expr-post-quote -> base-expr-postable post-mdn-expr
  ($2 $1)
mdn-expr-post-quote -> base-expr
  $1

post-mdn-expr -> post-mdn-expr-1 post-mdn-expr
  (lambda (e) ($2 ($1 e)))
post-mdn-expr -> post-mdn-expr-1
  $1

post-mdn-expr-1 -> list-notation
  (lambda (e) (cons e $1))
post-mdn-expr-1 -> LBRACKET list-content RBRACKET
  (lambda (e) (cons 'bracketaccess (cons e $2)))
post-mdn-expr-1 -> curly-infix
  (lambda (e) (list e $1))

list-notation -> LPARENS list-content RPARENS
  $2
; CONS = . i.e. the dotted-pair operator
list-content -> any-space* CONS any-space* mdn-expr any-space*
  $4
list-content -> any-space* mdn-expr list-content
  (cons $2 $3)
list-content -> any-space*
  '()

base-expr-postable -> SYMBOL
  $1
base-expr-postable -> list-notation
  $1
base-expr-postable -> bracket-notation
  $1
base-expr-postable -> curly-infix
  $1

; basically, these cases involve calling
; the built-in reader.
base-expr -> STRING
  $1
base-expr -> NUMBER
  $1
base-expr -> OTHER ; i.e. for #x reader
  $1
base-expr -> base-expr-postable
  $1

; again, hook for language-specific bracket meanings
bracket-notation -> bracket-notation-scheme
  $1
bracket-notation-scheme -> LBRACKET list-content RBRACKET
  $2
bracket-notation-arc -> LBRACKET list-content RBRACKET
  (list 'lambda (list '_) $2)

anyone find more bugs?

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 29 Jun 2012 21:24
Picon
Gravatar

Re: Arne Babenhauserheide proposal: use "." on own line instead of "group"

dwheeler mentioned the use of "\" for the GROUP character.  It happens to be the same as the SPLICE character.  My initial instinct is that this is a non-breaking change, i.e. using the same character for both will not break things, as long as we remove the SPLICE-at-the-eol rule (i.e. only allow SPLICE at the start or in the middle of things).  This means that the "GROUP" meaning of the character is not ambiguous with SPLICE-at-the-eol - remember, a "\" on a line by itself is either GROUP eol or SPLICE eol.

On Sat, Jun 9, 2012 at 7:04 PM, Arne Babenhauserheide <arne_bab-S0/GAf8tV78@public.gmane.org> wrote:
Hi,

At Wed, 23 May 2012 12:54:18 -0400 (EDT),
David A Wheeler wrote:
>
> Alpheus Madsen <alpheus.madsen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > One thought I've been wanting to experiment with, but haven't had the time to attempt to implement, is to use a double-indent to indicate groups.
>
> I think that's even worse.  It's very unreadable.  It's also ambiguous for the first indent; does "two spaces" mean an indent of two spaces, or a double-indent for one-space indenting?

Using double indent had also been my first idea, but I discarded it, because the meaning of the double indent would not be obvious without the less-indented line which comes later - it would be ambigous.

example:

(let
    ((a b)(c d))
  (e))

becomes

let
   a b
   c d
 e

Imagine 5 let arguments and you cannot know anymore if it’s double-indented.

Compare

let
 .
   a b
   c d
 e

The reason why I chose the . is to avoid adding any new syntax elements. . is already used to create cons-cels, but it has little use on its own:

(if (equal (. (quote "abc")) (quote "abc")) t)

; this syntax would be invalid with the .-notation.
if
 equal
   .
     quote "abc"
   quote "abc"
t

Also I like about the . that it is so small: It is almost like double indent, but explicit. And it scales:

(a (((((b c))))))

a
 .
   .
     .
       .
         b c

here it is explicit what happens, even though the code is evil.

Best wishes,
Arne

PS: Only answering now, because I we just moved, so I was overloaded for quite some time.

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 29 Jun 2012 21:39
Picon
Gravatar

Re: Proposed update and expansion of SRFI-49 (I-expressions) - indented s-expressions

Egil Moller also mentioned the following syntax:

'
...' x y

(where the initial . are spaces)

Unfortunately this is not supported by the currently defined parser above for i-expr.

possibly:

(i-expr lvl) -> QUOTE eol-empty-lines (body inlvl), if (> inlvl lvl)
  (cons 'quote $3)

... with corresponding additions for QUASIQUOTE et al.  Note the following:

...'
.x

=> yields (quote), empty body (and a syntax error caught by the quote special form)

'
..'
....x

=> yields (quote (quote x)), which I think should be what we expect.

'
..x
..y

=> yields (quote x y), which, while wrong, is still what I expect.  It's not clear from this alone what it should mean.

Still, should this last case yield (quote (x y)) instead?  Does that make more sense?  In that case our modification should be:

(i-expr lvl) -> QUOTE eol-empty-lines (body inlvl), if (> inlvl lvl)
  (if (<= (length $3) 1)
      (cons 'quote $3)
      (list 'quote $3))

But I don't like this.  Compare:

'
..x y
=> (quote (x y))
'
..x
..y
=> (quote (x y))

with this:

foo
  x y
=> (foo (x y))
foo
  x
  y
=> (foo x y)

This seems to privelege QUOTE et al. too much.  Or should they indeed be priveleged?

On Sat, Jun 30, 2012 at 3:19 AM, Alan Manuel Gloria <almkglor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Sigh.  Let me redo mdn-expr

any-space -> SPACE | TAB | VTAB | FORMFEED | CR | LF | comment

; the core implementations here need to be
; factored out, as the sweet-expr parser needs
; to do similar processing when differentating
; between space-significant and space-insignificant
; quote.
mdn-expr -> QUOTE any-space* mdn-expr
  (list 'quote $3)
mdn-expr -> QUASIQUOTE any-space* mdn-expr
  (list 'quasiquote $3)
mdn-expr -> UNQUOTE any-space* mdn-expr
  (list 'unquote $3)
mdn-expr -> UNQUOTE-SPLICING any-space* mdn-expr
  (list 'unquote-splicing $3)
mdn-expr -> mdn-expr-post-quote
  $1

; use a different base-expr here:
; disallow post-mdn-expr after things
; like STRING, NUMBER, OTHER
mdn-expr-post-quote -> base-expr-postable post-mdn-expr
  ($2 $1)
mdn-expr-post-quote -> base-expr

  $1

post-mdn-expr -> post-mdn-expr-1 post-mdn-expr
  (lambda (e) ($2 ($1 e)))
post-mdn-expr -> post-mdn-expr-1
  $1

post-mdn-expr-1 -> list-notation
  (lambda (e) (cons e $1))
post-mdn-expr-1 -> LBRACKET list-content RBRACKET

  (lambda (e) (cons 'bracketaccess (cons e $2)))
post-mdn-expr-1 -> curly-infix
  (lambda (e) (list e $1))

list-notation -> LPARENS list-content RPARENS
  $2
; CONS = . i.e. the dotted-pair operator
list-content -> any-space* CONS any-space* mdn-expr any-space*
  $4
list-content -> any-space* mdn-expr list-content
  (cons $2 $3)
list-content -> any-space*
  '()

base-expr-postable -> SYMBOL
  $1
base-expr-postable -> list-notation
  $1
base-expr-postable -> bracket-notation
  $1
base-expr-postable -> curly-infix
  $1

; basically, these cases involve calling
; the built-in reader.
base-expr -> STRING
  $1
base-expr -> NUMBER
  $1
base-expr -> OTHER ; i.e. for #x reader
  $1
base-expr -> base-expr-postable
  $1

; again, hook for language-specific bracket meanings
bracket-notation -> bracket-notation-scheme
  $1
bracket-notation-scheme -> LBRACKET list-content RBRACKET
  $2
bracket-notation-arc -> LBRACKET list-content RBRACKET
  (list 'lambda (list '_) $2)

anyone find more bugs?

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Arne Babenhauserheide | 30 Jun 2012 15:06
Picon
Gravatar

Re: Arne Babenhauserheide proposal: use "." on own line instead of "group"

Hm, I did not even know about the splice rule.

So, if it’s already necessary for syntax, \ would indeed be equivalent.

I’m just used to using it for escaping special characters, so it seems
odd to me to see it on a line on its own :)

Best wishes,
Arne

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Alan Manuel Gloria | 30 Jun 2012 17:08
Picon
Gravatar

Re: Arne Babenhauserheide proposal: use "." on own line instead of "group"



On Sat, Jun 30, 2012 at 9:06 PM, Arne Babenhauserheide <arne_bab-S0/GAf8tV78@public.gmane.org> wrote:
Hm, I did not even know about the splice rule.

So, if it’s already necessary for syntax, \ would indeed be equivalent.

I’m just used to using it for escaping special characters, so it seems
odd to me to see it on a line on its own :)

Best wishes,
Arne

Do be aware that the \ splice thing is not yet officially part of sweet-expressions; dwheeler made a draft of the splice rules but hasn't made a 0.3 sweet-expressions spec including it.

For now I think we should investigate the following alternatives:

1.  \ = GROUP = SPLICE, remove SPLICE-at-the-eol rule.

2.  . = GROUP, \  = SPLICE
2.1.  remove SPLICE-at-the-eol rule.
2.2. don't remove SPLICE-at-the-eol rule.

Sincereyl,
AmkG
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@...
https://lists.sourceforge.net/lists/listinfo/readable-discuss
Arne Babenhauserheide | 30 Jun 2012 20:24
Picon
Gravatar

Re: Arne Babenhauserheide proposal: use "." on own line instead of "group"

> Do be aware that the \ splice thing is not yet officially part of
> sweet-expressions; dwheeler made a draft of the splice rules but hasn't
> made a 0.3 sweet-expressions spec including it.

Do you mean the one here?
- http://www.dwheeler.com/readable/sweet-expressions.html

> - If it's the last character of the line (other than 0 or more
>   spaces/tabs), then the newline is considered a space, and the next
>   line's indentation is irrelevant. This continues the line. (Note
>   that comments cannot follow, because that would be confusing.)

This sounds quite interesting, because it is a standard known to many
people (from bash and python :) ).

> - If it's between items on a line, it's interpreted as a line break to
>   the same indentation level.

This sounds quite, though.  It gives \ doublemeaning. And not being
able to add comments behing the \ looks rather like trying to avoid
making the ambiguity introduced by the inline \.

I’m already not completely happy about using . for groups (because it
introduces additional rules - but it already is a special syntax
element, so it does not hurt too much).

But at least in elisp, the following is valid syntax:

(defun \ () 
       (message "\\"))
(\ )  

This is not, though:
(\).

So I am pretty certain, that (defun \ () ()) just defines " " to be a
function… though I’m not sure about that. 
(insert (stringp '(\ \ ))) complains that it is nil… 

Notes on that: 
http://ftp.gnu.org/old-gnu/Manuals/elisp-manual-21-2.8/html_node/elisp_22.html

> - Otherwise, if it's at the beginning of a line (after 0+
>   spaces/tabs), it's ignored - but the first non-whitespace
>   character's indentation level is used.

It allows making structure with whitespace which is not interpreted by
the parser. And I think that makes it ambigous.

> For now I think we should investigate the following alternatives:
> 
> 1.  \ = GROUP = SPLICE, remove SPLICE-at-the-eol rule.
> 
> 2.  . = GROUP, \  = SPLICE
> 2.1.  remove SPLICE-at-the-eol rule.
> 2.2. don't remove SPLICE-at-the-eol rule.

or:
2.3 remove SPLICE inline rule

Best wishes,
Arne

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss

Gmane