-
Notifications
You must be signed in to change notification settings - Fork 2
Grammar Reuse
It can happen that you have a domain and a grammar, and you want to reuse them in another domain and grammar which are supersets of the formers, respectively. E.g. a programming language domain can use an expression domain (note that MiniPL grammar does not reuse Expr grammar, because MiniPL grammar is not a strict superset of Expr grammar due to the different grammar rules related to expressions; thus only MiniPL domain reuses Expr domain).
Let's see an example for reuse.
MyExpression domain:
namespace MyExpression
{
public class Domain : Sarcasm.DomainCore.Domain<DomainDefinitions.Expression> { }
namespace DomainDefinitions
{
public abstract class Expression
{
}
// etc.
}
}
The reuse of a domain is simple, just use the definitions of MyExpression domain in MyPL domain.
using DE = MyExpression.DomainDefinitions;
namespace MyPL
{
public class Domain : Sarcasm.DomainCore.Domain<DomainDefinitions.Program> { }
namespace DomainDefinitions
{
public class Program
{
// ...
}
// ...
public class LocalVariable
{
public Name Name { get; set; }
public Type Type { get; set; }
[Optional]
public DE.Expression InitValue { get; set; } // reuse of MyExpression domain
}
// etc.
}
}
MyExpression grammar:
using DE = MyExpression.DomainDefinitions;
namespace MyExpression
{
public class Grammar : Sarcasm.GrammarAst.Grammar<DE.Expression>
{
public class BnfTerms
{
public readonly BnfiTermRecord<DE.Expression> Expression = new BnfiTermChoice<DE.Expression>();
internal BnfTerms(TerminalFactoryS TerminalFactoryS)
{
// ...
}
}
public readonly BnfTerms B;
public Grammar()
: base(new MyExpression.Domain())
{
B = new BnfTerms(new TerminalFactoryS(this));
this.Root = B.Expression;
B.Expression.SetRuleOr(
// ...
);
// etc.
}
}
}
You can reuse one or more grammars by composition, i.e. you have the other grammars inside your grammar as members. You also need to call IncludeGrammar
in your grammar's constructor.
MyPL grammar:
using D = MyPL.DomainDefinitions;
using DE = MyExpression.DomainDefinitions;
namespace MyPL
{
public class Grammar : Sarcasm.GrammarAst.Grammar<D.Program>
{
public class BnfTerms
{
BnfiTermRecord<D.Program> Program = new BnfiTermRecord<D.Program>();
BnfiTermRecord<D.LocalVariable> LocalVariable = new BnfiTermRecord<D.LocalVariable>();
internal BnfTerms(TerminalFactoryS TerminalFactoryS)
{
// ...
}
}
private readonly MyExpression.Grammar myExpressionGrammar;
public readonly BnfTerms B;
public readonly MyExpression.Grammar.BnfTerms BE;
public Grammar()
: base(new MyPL.Domain())
{
myExpressionGrammar = new MyExpression.Grammar(new MyExpression.Domain());
IncludeGrammar(myExpressionGrammar);
B = new BnfTerms(new TerminalFactoryS(this));
BE = myExpressionGrammar.B;
this.Root = B.Program;
B.Program.Rule =
// ...
;
B.LocalVariable.Rule =
B.VAR
+ B.Name.BindTo(LocalVariable, t => t.Name)
+ B.COLON
+ B.Type.BindTo(LocalVariable, t => t.Type)
+ (B.LET + BE.Expression) // reuse of MyExpression grammar
.QRef().BindTo(LocalVariable, t => t.InitValue)
;
// etc.
}
}
}
You can reuse formatters as well.
MyExpression formatter:
namespace MyExpression
{
public class Formatter : Sarcasm.Unparsing.Formatter
{
private readonly Grammar.BnfTerms B;
public Formatter(Grammar grammar)
: base(grammar)
{
this.B = grammar.B;
}
}
// ...
}
MyPL formatter:
namespace MyPL
{
public class Formatter : Sarcasm.Unparsing.Formatter
{
private readonly Grammar.BnfTerms B;
private readonly MyExpression.Grammar.BnfTerms BE;
public Formatter(Grammar grammarMyPL)
: base(grammar)
{
this.B = grammarMyPL.B;
this.BE = grammarMyPL.BE;
}
}
// ...
}
If you would like to download Sarcasm SDK, continue with Download.