#847 serialization syntax question

jsendra Wed 2 Dec 2009

This paragraph is part of examples/fwt/richText.fan. I have a question about syntax of line marked with // ---------------------

Window
{
  title = "RichText Demo"
  InsetPane
  {
    RichText
    {
      model=doc
      font = doc.defFont
      //hbar.onModify.add(&onScroll("hbar"))
      //vbar.onModify.add(&onScroll("vbar"))
      //onVerify.add |Event e| { echo("verify: $e.data") }
      //onVerifyKey.add |Event e| { echo("verify: $e") }
      //onSelect.add |Event e| { echo(e) }
    },
  },;  // ---------------------------------
  size = Size(600,600)
}.open

";" is a separator, and newline is a separator (two consecutive separators). But ";" is mandatory: without it, compiler detects an error

(42,7): Invalid args add(fwt::Widget?), not (gfx::Size)

In my understanding, Windows may contain a list of panes, so "," afer InsetPane{..} adds it to the list, and ";" marks the end of that list. But serialization syntax defines eos as ";"|newline

brian Wed 2 Dec 2009

That one is a little tricky, but the reason is because an it-block collection is a single statement, not a series of statements (from the grammar perspective):

<itAdd> :=  <expr> ("," <expr>)* <eos>

NOTE: that I just noticed that <eos> is missing in Grammar doc.

So the trailing comma is inside the itAdd statement, and a newline doesn't actually terminate the statement since the grammar expects another comma.

There was some debate about this little problem, but in the end the comma won out as the operator - see #508.

tactics Wed 2 Dec 2009

If you "desugared" the collection comma syntax, what you'd get is:

Window
{
  title = "RichText Demo"
  add(InsetPane
  {
    add(RichText
    {
      model=doc
      font = doc.defFont
    })
  });
  size = Size(600,600)
}.open

Once you have done this, the wayward semicolon is redundant, and can be removed.

When you have multiple items to add, you put commas at the end of each line, optionally omitting the last one:

Foo
{
  Bar("A child"),
  Bar("Another child"),
  Baz("A third child")
}

When there's only one item, the comma is required:

Foo
{
  Bar("The only child"),
}

If you add a line under that, Bad Things happen, and the compiler thinks you're trying to add another item to the list:

Foo
{
  Bar("The only child"),
  doStuff
}

But you don't want to add doStuff to the collection. You just want to execute it. So by adding that semicolon in there, you tell the compiler "that's the end of things to add".

Foo
{
  Bar("The only child"),;
  doStuff
}

Now, Bar("The only child") is added to the Foo object you create and doStuff is executed, and whatever value it might return is thrown away.

Login or Signup to reply.