Template language sections | |
---|---|
templates | Section with templates t* |
template options | Section with options o* |
Productions | |
Sort = < e* > | Template with elements e* |
Sort.Constructor = < e* > | Template with elements e* |
Sort = [ e* ] | Template with elements e* (alt. brackets) |
Sort.Constructor = [ e* ] | Template with elements e* (alt. brackets) |
Placeholders | |
<Sort> | Placeholder (1) |
<Sort?> | Optional placeholder (0..1) |
<Sort*> | Repetition (0..n) |
<Sort+> | Repetition (1..n) |
<Sort*; separator="\n"> | Repetition with separator |
<Sort; text="hi"> | Placeholder with replacement text |
<Sort; hide> | Placeholder hidden from completion template |
Escapes | |
<\\\'\"\ \t\r\n> | Element containing escaped characters |
<\u0065> | Unicode escape |
<\\> | Escape next line break |
<> | No output; layout will be allowed here in the grammar |
\< , \> , \[ , \] , \\ | Escaped brackets / backslash (prefer alt. brackets) |
Priority specification | |
context-free priorities | Refer to templates using sort and constructor name |
Lexical syntax | |
lexical syntax | Lexical syntax similar to SDF |
Template options | |
keyword -/- [A-Za-z0-9] | Follow restriction for keywords |
tokenize : "()" | Layout is allowed around (sequences of) these characters |
newlines : none | Experimental: generate grammar that requires newline characters. Possible values: none , separating , leading , trailing |
hello world
maps to "hello" "world"
, thus allowing any layout between the two tokens.
tokenize
option, and any other characters. That is, if()
maps to "if" "(" Exp ")"
, to allow layout between the if keyword and the parentheses.
separator
option containing any non-layout characters is given, the placeholder maps to a list with separator.
box2text-string
strategy from libstratego-gpp.
For example, for a simple plus-expression syntax template:
Exp.Plus = <<Exp> + <Exp>> {left}the pretty printing strategy that may be generated is:
prettyprint-Exp: Plus(a, b) -> [ H([SOpt(HS(), "0")], [ <pp-one-Z(prettyprint-Exp)> a, S(" + "), <pp-one-Z(prettyprint-Exp)> b ]) ]As you can see, the pretty printing strategies return a list of boxes that the caller should wrap in a
V
or Z
box (among other things, that is what pp-one-Z
does).
The user is responsible for this when invoking one of the prettyprint-*
strategies from their code!
All pretty printing strategies that are specific to a symbol are hooked up to one global prettyprint-LanguageName
strategy, so that it is easy to pretty print an arbitrary subtree of an AST without knowing the type of the root node in advance:
prettyprint-LanguageName = prettyprint-Exp
sdf2parenthesize
does exactly this, and is integrated into SpoofaxLang? via the parenthesize-LanguageName
strategy.
Invoking the parenthesize-LanguageName
strategy results in the addition of Parenthetical
constructors to the AST at every place where the structure of the AST conflicts with the operator priorities specified in the grammar.
The generated pretty printer knows how to handle the Parenthetical
constructor, because a syntax template for parentheses with the bracket
attribute, such as:
Exp = <(<Exp>)> {bracket}generates the pretty printing strategy:
prettyprint-Exp: Parenthetical(a) -> [ H([SOpt(HS(), "0")], [ S("("), <pp-one-Z(prettyprint-Exp)> a, S(")") ]) ]
prettyprint-LanguageName-string = parenthesize-LanguageName ; prettyprint-LanguageName ; !V([], <id>) ; box2text-string(|100)-- TobiVollebregt - 01 Feb 2012