Updated SRFI-110 posted. David A. Wheeler (06 Aug 2013 12:07 UTC)
Re: Updated SRFI-110 posted. John Cowan (06 Aug 2013 14:46 UTC)
Re: Updated SRFI-110 posted. David A. Wheeler (06 Aug 2013 17:34 UTC)
Better error resync - read until un-indented line David A. Wheeler (06 Aug 2013 22:11 UTC)

Re: Updated SRFI-110 posted. John Cowan 06 Aug 2013 14:46 UTC

David A. Wheeler scripsit:

> Thoughts?

Below is a version with no Java cruft, which I find more readable.

// Production "collecting_content" returns a collecting list's contents.
// Precondition: After collecting start and horizontal spaces.
// Postcondition: Consumed the matching COLLECTING_END.
// FF  formfeed (\f aka \u000c), VT  vertical tab (\v aka \u000b)

collecting_content
  : it_expr collecting_content
  | comment_eol    collecting_content
  | (FF | VT)+ EOL collecting_content
  | COLLECTING_END;

collecting_list
  : COLLECTING hs collecting_content hs;

// Process line after ". hspace+" sequence.  Does not go past current line.

post_period
  : skippable post_period
    | n_expr hs skippable* (n_expr error)?
    | collecting_list skippable* (n_expr error)?
    | /*empty*/;

// Production "line_exprs" reads the 1+ n-expressions on one line; it will
// return the list of n-expressions on the line.  If there is one n-expression
// on the line, it returns a list of exactly one item.
// Precondition: At beginning of line after indent
// Postcondition: At unconsumed EOL

line_exprs
  : PERIOD /* Leading ".": escape following datum like an n-expression. */
      (hspace+ post_period
       | /*empty*/)
  | collecting_list
      (rest_of_line
       | /*empty*/)
  | n_expr_first /* Only match n_expr_first */
      ((hspace+ (rest_of_line
                 | /*empty*/))
       | /*empty*/);

// Production "rest_of_line" reads the rest of the expressions on a line,
// after the first expression of the line.
// Precondition: At beginning of non-first expression on line (past hspace)
// Postcondition: At unconsumed EOL

rest_of_line
  : PERIOD hspace+ post_period /* Improper list */
  | skippable (rest_of_line | /*empty*/)
  | collecting_list
    (rest_of_line
     | /*empty*/)
  | n_expr
      ((hspace+ (rest_of_line
                 | /*empty*/))
       | /*empty*/);

// Production "body" handles the sequence of 1+ child lines in an it_expr
// (e.g., after "line_expr"), each of which is itself an it_expr.
// It returns the list of expressions in the body.

body
  : it_expr
     (same
       (? >   it_expr DEDENT // Improper list
       |? > body
       |? > body)
     | DEDENT);

// Production "normal_it_expr" is an it_expr without a special prefix.

normal_it_expr returns [Object v]
  : line_exprs (
     GROUP_SPLIT hs // split
     | SUBLIST hs it_expr
     | comment_eol // Normal case, handle child lines if any:
       (INDENT body
        | /*empty*/ /* No child lines */));

// These are it_expr's with a special prefix like \\ or $:

datum_comment_line
  : DATUM_COMMENTW hs
    (it_expr | comment_eol INDENT body);

group_line
  : (GROUP_SPLIT | scomment) hs /* Initial; Interpet as group */
      (it_expr /* Ignore initial GROUP/scomment */
       | comment_eol
         (INDENT body /* Normal GROUP use */
          | /*empty*/));

sublist_line returns [Object v] // "$" first on line
  : SUBLIST hs it_expr;

abbrevw_line
  : abbrevw hs
      (comment_eol INDENT body
       | it_expr);

// Production "it_expr" (indenting sweet-expression)
// is the main production for sweet-expressions in the usual case.
// Precondition: At beginning of line after indent, NOT at an EOL char
// Postcondition: it-expr ended by consuming EOL + examining indent

it_expr
  : normal_it_expr
  | datum_comment_line
  | group_line
  | sublist_line
  | abbrevw_line      ;

// Production "initial_indent_expr" is for an expression starting with indent.

initial_indent_expr
  : (INITIAL_INDENT | separator_initial_indent) (scomment hs)*
    (n_expr
     | comment_eol);

// Production "t_expr_real" handles special cases, else it invokes it_expr.

t_expr_real
  : comment_eol    r1t_expr_real // Skip initial blank lines
  | (FF | VT)+ EOL r2t_expr_real // Skip initial FF|VT lines
  | EOF                           // End of file
  | initial_indent_expr
  | it_expr                     /* Normal case */;

// Production "t_expr" is the top-level production for sweet-expressions.

t_expr
  : t_expr_real
      ; retry if empty_value.

--
Is a chair finely made tragic or comic? Is the          John Cowan
portrait of Mona Lisa good if I desire to see           xxxxxx@ccil.org
it? Is the bust of Sir Philip Crampton lyrical,         http://ccil.org/~cowan
epical or dramatic?  If a man hacking in fury
at a block of wood make there an image of a cow,
is that image a work of art? If not, why not?               --Stephen Dedalus