Goldie Homepage Documentation (v0.3) |
Static And Dynamic StylesGoldie supports two different styles of interfaces: a static-style and a dynamic-style. Both styles have pros and cons, and are suitable for different purposes. The differences are explained in the comparison chart and examples below. Note that if you use StaticLang to embed a language directly into your program, you can switch back and forth between static and dynamic styles however you wish. "Which Style Should I Use?"You can use whichever you want, but the recommended rule of thumb is: Use dynamic-style if you're doing something that isn't possible in static-style (like Parse or Parse Anything). Otherwise, use static-style. Most apps will probably want to use static-style. Comparison Chart
ExamplesThe following examples use the calc language. Example: Loading a LanguageStatic-style
// Run "staticlang calc.cgt /pack:myapp.mylangs" at command-line
import goldie.all;
import myapp.mylangs.calc.all;
// Use 'language_calc'
Dynamic-styleDo the same as static-style, or: import semitwist.util.io : getExecPath; import goldie.all; Goldie.langDir = getExecPath()~"{path to your cgt files}"; Language language_calc = Goldie.loadLanguage("calc"); // Use 'language_calc'Or: import goldie.all; Language language_calc = Goldie.loadCGT("calc.cgt"); // Use 'language_calc'Example: Parsing a sourceStatic-style
auto rootToken = language_mylang.parseCode(src).parseTree;
The variable rootToken is of type Token_mylang!("<Add Exp>") (see Token_ for details). !( ) Dynamic-style
auto rootToken = language_mylang.parseCodeX(src).parseTreeX;
The variable rootToken is of type Token. Example: Checking a token's symbolStatic-style
Just like checking for a rule (see below),
but with Token_calc!("<Add Exp>") instead of
Token_calc!("<Add Exp>", "<Add Exp>", "+", "<Mult Exp>")
Dynamic-style
bool isAddExp(Token tok)
{
return tok.name == "<AddExp>";
// Or to disambiguate (See the "Ambiguous Symbols" page):
return tok.name == "<AddExp>" && tok.type == SymbolType.NonTerminal;
}
Example: Checking a token's rule and retrieving a sub-tokenStatic-style
void useMultExpFromAddExp(T)(T tok)
{
// This represents the rule: <Add Exp> ::= <Add Exp> '+' <Mult Exp>
static if(is( T == Token_calc!("<Add Exp>", "<Add Exp>", "+", "<Mult Exp>") ))
{
auto multExp = tok.sub!(2);
}
else
// Doesn't match: Caught at compile-time
}
Or: void useMultExpFromAddExp(Token_calc!("<Add Exp>", "<Add Exp>", "+", "<Mult Exp>") tok) { auto multExp = tok.sub!(2); } // Omit this to catch "doesn't match" at compile-time: void useMultExpFromAddExp(Token tok) { // Doesn't match: Caught at **run-time** }Or (not as highly recommended as the above): void useMultExpFromAddExp(Token unknownTok) { if(auto tok = cast(Token_calc!("<Add Exp>", "<Add Exp>", "+", "<Mult Exp>"))unknownTok) { auto multExp = tok.sub!(2); } else // Doesn't match: Caught at **run-time** }Dynamic-style
void useMultExpFromAddExp(Token tok)
{
// This represents the rule: <Add Exp> ::= <Add Exp> '+' <Mult Exp>
if(tok.matches("<Add Exp>", "<Add Exp>", "+", "<Mult Exp>"))
{
auto multExp = tok.subX[2];
}
}
More ExamplesFor a full-program example of static-style versus dynamic-style, see Calculator Static and Calculator Dynamic. |