Syntax ideas for CF3

Let the developers know what you think of the software and what can be done to either improve the CFDG language or the Context Free program.

Moderators: MtnViewJohn, chris, mtnviewmark

Post Reply
User avatar
zol
Posts: 40
Joined: Sun Mar 23, 2008 4:14 pm

Syntax ideas for CF3

Post by zol »

I like the general plan for shape and rule layout in the spec, so I won't bother repeating them here. Familiarity assumed etc.

The basic goal behind these suggestions is to retain the uncluttered and non-intimidating feel of version 2, while providing enough syntactic discipline to avoid ambiguity as well as assist visual navigation and discrimination among different parts of code.

Preliminary assumption: An expression is readily seen and parsed as a single token.
This is important for allowing whitespace to delimit tokens without ambiguity.

Expressions:
Non-simple expressions in foreign contexts are always fully enclosed by parens, "( )", which visually represent a single return value.
This includes function calls: the function name and arguments together correspond to a single return value.
    ([color=#0000BF]select[/color] num (2 - 1) 2 -1 (- 1) (1/2) ([color=#0000BF]sqrt[/color] var))
Note that parentheses unambiguously separate arguments even if whitespace is omitted.
    [size=85]An alternative is just to prohibit space between unenclosed expression elements. "function(args)" style would therefore also fulfil the main requirement, but it looks more cluttered to me, and the habitual connection between neighbouring words - function and variable names - would go the wrong way.[/size]
Tuples are implicit within math functions that use them, represented as a space delimited list within the function parens.

Tuples:
Explicit tuples are represented by brackets, "[ ]", with space delimited values.
These include adjustment, rule, and path parameters.
Background, size, and tile directives should probably also use tuples given their limited effects.

Adjustment functions always take exactly one tuple as argument.
    [color=#800000]skew[/color] [30 40]
Adjustment 1-tuples do not require brackets.
    [color=#800000]size[/color] 2
Adjustment groups and parameter definitions:
In contexts where tokens are required to occur in associated pairs, the parser can pair them correctly without additional clues, and all tokens are delimited by whitespace alone.
    Parameter definition pairing: [color=#000080]type[/color] [color=#008000]name[/color] Adjustment group pairing: [color=#000080]function[/color] [color=#008000]argument[/color]
Adjustment groups are represented by braces, "{ }", with space delimited tokens.

Transform type values are defined using adjustment group syntax, including braces.
    myShape [3 {x [1 2]}]
Miscellaneous:
In general, I favour using keywords, tuples and code blocks for a consistent feel, avoiding special purpose syntax.

Variable assignment:
    [color=#800000]set[/color] name value_expression
Loops:
    [color=#800000]loop[/color] name control_tuple {adjustments} [color=#FFFFFF]........[/color]loop_body [color=#800000]finally[/color] [color=#FFFFFF]........[/color]finally_body
and anonymous
    [color=#800000]loop[/color] count {adjustments} [color=#808080]etc.[/color]
Control tuples have consistent order.
1: count
2: count start
3: count start step
Note that these parameters allow the final value to adjust correctly and automatically with other changes.

Loop 1-tuples do not require brackets.

I think it's clear enough how this style could be applied elsewhere, so I won't spell it out.


Possible extensions:

Parameters:
1) Definitions can have default values, bound to the name using "=" without intervening space.
2) Values can be supplied by name, again using "=" as above, for both shape replacements and adjustment functions.

For illustration only, imagine an adjustment function definition analogous to shape definition
    [color=#FF8000]adjustment[/color] size [[color=#000080]number[/color] x [color=#000080]number[/color] y=x [color=#000080]number[/color] z=1]
So we could use "size [3 z=-1]" instead of "size [3 3 -1]"

Transform type values:
Explicit chaining within expressions.
    myShape {tr (trans & {z -1 s 2})}
equivalent to
    myShape1 {tr trans} ... [color=#FF8000]shape[/color] myShape1 { myShape {z -1 s 2} }
Of course the prohibition on derivative transform parameters would apply.

Other:
I have deleted the original section on re-write filters as I did not explain what I was referring to, nor make a definite proposal.
I will cover them again when I have the opportunity to do a better job of it.

User avatar
MtnViewJohn
Site Admin
Posts: 882
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

Re: Syntax ideas for CF3

Post by MtnViewJohn »

Expressions:
I can't see that using s-expression syntax for functions mixed with infix notation for math operators is going to be non-intimidating. Euler notation, with the function name outside the parentheses, is very familiar to anyone who has studied algebra. S-expressions will only be familiar to people with CS degrees.

The question of using white space to separate function arguments versus using commas is interesting. For simple arguments it does cut down on clutter. But for anything more complex white space separation requires extra parentheses that are not needed with comma separation. Euler notation uses commas. So the commas are clutter if you don't need them but the parentheses are clutter if they are only needed because there are no commas. Hard to call a winner.

Overall I think that the benefit of using the universally familiar euler notation is greater than the benefit of an innovative non-euler notation.

Tuples:
Using this tuple syntax for adjustments seems OK. I was thinking of using euler notation, but making it optional:
CIRCLE { size 3 4 skew(30, 40) }

Using your tuple syntax for adjustments and rule parameters is a very interesting idea. Right now the parser uses <> brackets for rule parameters because all of the other brackets types result in reduce/reduce parser errors (which are evil). But your idea results in a more unified syntax and fixes the reduce/reduce issue in the parser.

Re-write filters:
Does this have to do with adjustments that are reordered in TRSSF order? I like the idea of using {} brackets for all adjustments, and freeing up [] brackets for tuples. The canonical ordered adjustments are a hand-holding feature for people who can't wrap their minds around chaining of affine transforms. I have never been very happy with using {} brackets and [] brackets for the two type of adjustments and Mark has flat-out hated it from day one. But I still think that canonical order is fine for most people most of the time so I want to keep it and make it easy to use.

So instead of a filter I would propose to think of having a unary (prefix) operator that operates on an adjustment list be reordering it to canonical order:
*{ x 2 s [3 5]}
Basically your third option, but with the operator in front.

Assignment:
I like using '=' to denote assignment and in named loops. It's a syntax that people are very familiar with. But it does mean that the equality operator has to be '==', like in C. Maybe I could borrow from Pascal and use ':=' or '<-' for assignment and '=' for equality. I totally forgot to have an anonymous loop syntax.

Parameters:
Having default parameters is an interesting idea, but it hinges on whether parameters behave like C++ template parameters or like Haskell curried parameters. The Haskell approach is powerful but complicated. It would allow you to bind some parameters to a shape, pass this partially bound shape off to another rule or assign it to a variable, and then later bind the remaining parameters and invoking the shape. But all parameters must be bound, in left to right order.

C++ template rules would allow default values and named assignment.

User avatar
zol
Posts: 40
Joined: Sun Mar 23, 2008 4:14 pm

Re: Syntax ideas for CF3

Post by zol »

I had assumed from the spec that version 3 syntax needed to be less flexible than version 2, but your post suggests that I was imagining things.

Mathematical expressions:
If exposed function names are not a problem anywhere that numerical expressions are required, then the main reason for using s-expressions is removed, and a mixture of infix and Euler notation is fine.
    {x sqrt(1/2) f 22.5} myVar = log(10)
I'll also say that disambiguating "-" based on presence or absence of space seems perfectly reasonable and adequate.
  • "-" is unary only if there is a term directly after it but not directly before it.
    e.g. -.3 -cos(8*9) -(2/3)
Adjustments:
MtnViewJohn wrote:Tuples:
Using this tuple syntax for adjustments seems OK. I was thinking of using euler notation, but making it optional:
CIRCLE { size 3 4 skew(30, 40) }
This removes the reason I suggested explicit tuple syntax for adjustments in the first place, so I don't know whether it's still worth considering.

If there is no problem continuing to allow multiple arguments to an adjustment, grouping by context as in version 2, then there's no need for additional punctuation to perform the same role.
    CIRCLE { size 3 4 skew 30 40 }
So, why not just do the easy and obvious thing and retain the version 2 approach?
  • The parser can already associate multiple arguments with each adjustment function, it does not require any argument grouping syntax.
  • The parser can already separate space-delimited elements into multiple arguments, it does not require any new delimiters.
  • What it actually requires is a way to combine multiple elements into a single argument.
Under these conditions, Euler notation does things the hard way.
First it switches the default handling of all the symbols in an adjustment's argument list from separated to combined. Then it requires commas to separate all of its arguments explicitly.

A more efficient approach is to retain the space-delimited default separateness, and use parens only for individual arguments that need to combine multiple elements. Doing just the job that needs doing.

Other reasons to prefer the space-and-paren approach over Euler notation:
  • Parens can be added to individual arguments, whereas Euler must apply to all arguments. There would be some pressure to employ Euler routinely and needlessly simply to avoid extra editing in case of argument modifications.
  • For arguments consisting of multiple symbols, parens are better at presenting them as visually distinct units than commas.
  • Extra space will be desirable anyway, particularly if you want to distinguish commas clearly from decimal points.
  • Euler has no more or less effect than one set of parens per argument, and there are typically fewer than three complex arguments per adjustment function, so it isn't economical by character count.
Re-write operator:
Yes. I was actually planning to change my proposal to exactly that. A prefix unary operator.
The postfix version was basically quoting the manner in which text is marked if there are footnotes, which I thought might resonate more with non-programmers.

Assignment and loop control:
I'm easy regarding variable assignment (although I don't see a need for the terminating semicolon here), but I find the extra "=" and parens superfluous and untidy for loop control.
Perhaps I am overly paranoid about procedural programming idioms muscling in where they are not useful, but I can't help but see the C in them.

Boolean/relational operators
I think equality should use "==" regardless. A matching suite of operators would be best, and C has a good one.

User avatar
MtnViewJohn
Site Admin
Posts: 882
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

Re: Syntax ideas for CF3

Post by MtnViewJohn »

Tuples:
OK, let's keep the tuple operator (,) rather than introduce a tuple syntax [].

The point of using euler notation in adjustments is not that it is always better, it just comes for free when we have a tuple operator. Would people write skew(30, 40) instead of skew 30 40? I hope not because leaving off the parens and comma is better style. But some people might prefer skew(30-a, 40-a) to skew (30-a) (40-a).

Re-write operator:
OK. I will incorporate this into the syntax and eliminate the expression syntax for adjustments, as we discussed privately.

Assignment and loop control:
Semicolon is history. I can't remember why it was ever there.

I can get rid of the '=' or the parentheses in the loop control but the parser fails if I get rid of both. This is fine with me because I like the '=', especially with the parens gone.

User avatar
zol
Posts: 40
Joined: Sun Mar 23, 2008 4:14 pm

Re: Syntax ideas for CF3

Post by zol »

MtnViewJohn wrote:But some people might prefer skew(30-a, 40-a) to skew (30-a) (40-a).
If this means that both options will be available then I'm satisfied. But I don't know what other people's preferences are.
I can get rid of the '=' or the parentheses in the loop control but the parser fails if I get rid of both. This is fine with me because I like the '=', especially with the parens gone.
That's better, and "=" does provide a nice semantic hint for those who might find it too abstract otherwise I suppose.

Other:
"k" for skew, "c" for sat (chromaticity/colourfulness)?
Last edited by zol on Mon Feb 07, 2011 2:50 pm, edited 1 time in total.

User avatar
MtnViewJohn
Site Admin
Posts: 882
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

Re: Syntax ideas for CF3

Post by MtnViewJohn »

zol wrote:Other:
"k" for skew, "c" for sat (chromaticity/colourfulness)?
I thought about adding more abbreviations but I realized that this would cause trouble for variable and parameter names. People will want to use short words for variable and parameter names but they can't use the names reserved for adjustment terms. I could tweak the parser to allow adjustment tokens as variable and parameter names but they would have to be wrapped in parentheses to force the right parsing context, while other variable names could be used "naked". This seems like a wrong direction to me, so I intend to make adjustment term names reserved and not create any new ones that are shorter than four letters.

Post Reply