ietf-mta-filters
[Top] [All Lists]

Re: I-D ACTION:draft-ietf-sieve-3028bis-04.txt

2005-07-22 01:34:51

On Thu, Jul 21, 2005 at 02:43:13PM -0700, Ned Freed wrote:
As to the idea of actually using formal grammar for this sort of thing, been
there, done that, bad idea. Having been on the receiving end of questions 
for
RFC 1521 issues, I can tell you that using subgrammars (or whatever the 
correct
term for this is) creates about 10X more confusion than clarity.

Too bad, but I guess a paragraph like

  All Sieve commands, including extensions, MUST be words of the following
  generic grammar with the start symbol "start".  They SHOULD be specified   
  using a specific grammar, though.

is not going to help most people a lot, despite specifying *exactly*
the same as RFC 3028.

The simple fact of the matter is that people just aren't that good at
extracting usage information from ABNF. THis isn't to say we should not 
have a
precise definition of the overall syntax in ABNF - implementors at the very
least need it - but using ABNF to provide usage information' goes too far. 

I built a full ABNF for my implementation to move as much as possible
from semantic analysis to syntactic analysis, but that is just one
possible approach.  I append my implementation notes, but they are
not meant as suggested change to the draft, but to illustrate the step
between RFC 3028 and actual code.  The { } specification is pretty
weak and just "worked for me".

I am pretty sure others use the generic ABNF for syntactic analysis,
following straightforward RFC 3028.  That is well possible and it does
not need a specific grammar.

The
form we use now is simple, easy to read, and gets the job done.

Once "Syntax" is replaced by "Usage", it is fine with me and I shall
agree to the next released draft.

Michael
----------------------------------------------------------------------
The grammar is specified in ABNF with two extensions to describe tagged
arguments that can be reordered and grammar extensions: { } denotes a
sequence of symbols that may appear in any order.  Example:

  options = a b c
  start =  { options }

is equivalent to:

  start =  ( a b c ) / ( a c b ) / ( b a c ) / ( b c a ) / ( c a b ) / ( c b a )

The symbol =) is used to append to a rule:

  start =  a
  start =) b

is equivalent to

  start =  a b

All Sieve commands, including extensions, MUST be words of the following
generic grammar with the start symbol "start".  They SHOULD be specified
using a specific grammar, though.

   argument        = string-list / number / tag
   arguments       = *argument [test / test-list]
   block           = "{" commands "}"
   commands        = *command
   string          = quoted-string / multi-line
   string-list     = "[" string *("," string) "]" / string
   test            = identifier arguments
   test-list       = "(" test *("," test) ")"
   command         = identifier arguments ( ";" / block )
   start           = command

The basic Sieve commands are specified using the following grammar, which
language is a subset of the generic grammar above.  The start symbol is
"start".

  address-part     =  ":localpart" / ":domain" / ":all"
  comparator       =  ":comparator" string
  match-type       =  ":is" / ":contains" / ":matches"
  string           =  quoted-string / multi-line
  string-list      =  "[" string *("," string) "]" / string
  address-test     =  "address" { [address-part] [comparator] [match-type] }
                      string-list string-list
  test-list        =  "(" test *("," test) ")"
  allof-test       =  "allof" test-list
  anyof-test       =  "anyof" test-list
  exists-test      =  "exists" string-list
  false-test       =  "false"
  true=test        =  "true"
  header-test      =  "header" { [comparator] [match-type] }
                      string-list string-list
  not-test         =  "not" test
  relop            =  ":over" / ":under"
  size-test        =  "size" relop number
  block            =  "{" commands "}"
  if-command       =  "if" test block *( "elsif" test block ) [ "else" block ]
  stop-command     =  "stop" { stop-options } ";"
  stop-options     =
  keep-command     =  "keep" { keep-options } ";"
  keep-options     =
  discard-command  =  "discard" { discard-options } ";"
  discard-options  =
  redirect-command =  "redirect" { redirect-options } string ";"
  redirect-options =
  require-command  =  "require" { require-options } string-list ";"
  require-options  =
  test             =  address-test / allof-test / anyof-test / exists-test
                      / false-test / true-test / header-test / not-test
                      / size-test
  command          =  if-command / stop-command / keep-command
                      / discard-command / redirect-command
  commands         =  *command
  start            =  *require-command commands

The extensions "envelope" and "fileinto" are specified using the following
grammar extension.

  envelope-test    =  "envelope" { [comparator] [address-part] [match-type] }
                      string-list string-list
  test             =/ envelope-test

  fileinto-command =  "fileinto" { fileinto-options } string ";"
  fileinto-options =
  command          =/ fileinto-command

The extension "copy" is specified as:

  fileinto-options =) ":copy"
  redirect-options =) ":copy"

And so on ...