Subject: Re: envelope test syntax?

From: Michael Haardt <[email-masked]>
Date: Thu, 13 May 2004 13:37:19 +0200

> I assume you're referring to the confusing text that includes things
> like "else" being a separate command, and "'elsif' must only follow
> 'if'" which is obviously incorrect.  OTOH I think the incorrectness
> there is not due to the documentation method, but in errors in the
> description.  i.e. the description could be corrected.  

IMHO, the documentation method asks for such problems.  When I first
read the paragraph, it sounded a little odd, but I probably assumed
that it was meant to describe the common "if elsif else" structure.

Later, when I worked on code and tried to find the grammar for the
structure, the mistake became obvious.

> > The ABNF
> > 
> >   if-command       = "if" test block *( "elsif" test block ) [ else block ]
> > 
> > is short and (hopefully:) correct.
>
>     closer when "else" is quoted :-)

Oops! Thanks for spotting that, the next Exim release will have a
fixed version.

> However there's still the issue of extensions: the syntax varies
> depending on what extensions are enabled.  Each extension can probably
> be specified via BNF, but how would you address optional grammar (i.e.
> as distinct from grammar that includes optional elements)?

Now I see your point: Each implementation contains the base grammar
plus all extensions, but an implementation that contains new tests
had to add the "test" rule.  How about another ABNF extension, e.g.
/=?

  rule             =  a
  rule             /= b

is equivalent to

  rule             =  a / b

The RFC would then contain:

  test             =  address-test / allof-test / anyof-test / exists-test
                      / false-test / true-test / header-test / not-test
                      / size-test / envelope-test

and extensions could specify:

  test             /= extension-test

If you took the rules from the RFC plus the rules for all extensions,
you had a correct grammar for the implementation.
 
> (That's not as thorny as self-modifying grammar of course.. a la
> typedef in C)

Types are usually checked at the semantic layer, probably for just that
reason.  Any set of extensions plus the base grammar yields a constant
grammar, so no problem there.  The generic Sieve grammar generates a
larger language than any implementation grammar, but it is only used to
ensure that extensions fit into Sieve.

> Do you think that SIEVE is unimplementable based on RFC3028?

I had to ask Tim several times for details.  "Unimplementable" is too
strong; I think of it as "incomplete in minor aspects".  Two examples
from the same README:

----------
Strings Containing Header Names

RFC 3028 does not specify what happens if a string denoting a header
field does not contain a valid header name, e.g. it contains a colon.
This implementation generates an error instead of ignoring the header
field in order to ease script debugging, which fits in the common
picture of Sieve.

Exists Test With Empty List Of Headers

The "exists" test only suceeds if all specified headers exist.  RFC 3028
does not explicitly specify what happens on an empty list of headers.
This implementation evaluates that condition with true, interpreting
the RFC in a strict sense.
----------

The above can but guessed by common sense, but a specification should not
leave anything to guess.  These things are clearly semantic, so again
the RFC shows how hard semantics are to describe with natural language
without leaving things out.

That's why I suggest to handle syntactic issues at the syntactic level:
Easy to use formal specifications exist, that don't leave anything
to guess, plus it makes an implementation easier.

Michael

---

From: Cyrus Daboo <[email-masked]>
Date: Thu, 13 May 2004 09:40:00 -0400

Hi Michael,

--On Thursday, May 13, 2004 1:37 PM +0200 Michael Haardt 
<[email-masked]> wrote:

> How about another ABNF extension, e.g.
> /=?
>
>   rule             =  a
>   rule             /= b

ABNF (RFC 2234) already has that - see section 3.3 in that document. The 
syntax is a little different from what you have above:

    rule            =/ b

The one thing that is missing from ABNF in my opinion is an operator to 
specify a list of items that can appear in any order. Tagged arguments in 
SIEVE is a good example of where that would be useful - also iCal (RFC 
2445) where properties within components can occur in any order.

-- 
Cyrus Daboo

---

From: "Mark E. Mallett" <[email-masked]>
Date: Fri, 14 May 2004 18:58:07 -0400

On Thu, May 13, 2004 at 01:37:19PM +0200, Michael Haardt wrote:
  [ skipping much that I have no quibble with ]

> reason.

True, type checking is a semantic issue (some of which can be done at
parse time), but that isn't what I was getting at.  "typedef" modifies
the language syntax.  Consider:

/*1*/    typedef unsigned int  myint;
/*2*/    myint x = 3;

Without line 1, line 2 has an invalid syntax.  This isn't a
semantic typechecking problem, it's strictly a syntax issue.
This is different from, say, function prototypes, because a function
reference whose only error is that it doesn't match a prototype
is still syntactically correct.

Relatedly, the SIEVE RFC doesn't really specify whether "require"
enables an extension syntax or merely use of an extension at run time.
For example, given this complete script:

    if false { fileinto "impossible"; }
    else { keep; }

Is that a syntax error because it is missing the "require"?  (I can't
imagine that it is: my own implementation says it's not.  But that
would be a lesser example of a self-modifying grammar.)

> the RFC in a strict sense.

How would you arrange to get an empty set of headers?

> to guess, plus it makes an implementation easier.

Still no argument there :-)

mm