Child pages
  • External calculations by Vlad

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

Following syntax make separation of the grammar and specific calculations on it.

Code Block
calcs type Compile; // type of named calculations, set of coordinated calculations aimed at particular task

calcs Compile for N2Syntax // implementation of 'Compile' calculations for 'N2Syntax' syntax module
{
  Start.CollectGlobalSymbols(rootNs : NamespaceSymbol) : void = NamespaceBody.CollectGlobalSymbols(rootNs); // calculation 'CollectGlobalSymbols' for rule 'Start'
  [Cached] Start.MakeContext(parent : Context) : Context = NamespaceBody.MakeContext(parent);
  Start.Typing() : void = NamespaceBody.Typing();

  ...

  ExtraFieldAttributes.IsCached() : bool
  {
    foreach(x when x.IsCached() in ExtraFieldAttributeLists)
      return true;
    false
  }

  // The calculation 'Typing' for rule 'Rule'. The 'Rule' is a alternativ rule (extensible).
  Rule.Typing(_baseRule : option[ExtensibleRuleSymbol], _precedence : int, _fieldName : option[string], context : Context, options : RuleDefinitionOptions) : N2.Model.Rule
  {
    | Sequence => // The entry for extention rule Sequence. It is can be arbitrary pattern on AST (Rule extention node).
      def bp1   = if (_precedence < 0) -_precedence + 1 else _precedence;
      def bp2   = if (_precedence < 0) -_precedence     else _precedence;
      def flat = List();
      def tryExtractSpaceSequence(rule : N2.Model.Rule) : void
      {
        // assume that 's' is generated whitespace rule
        match (rule)
        {
          | Sequence([String as call1, Call(s, 0) as call2])
          | Sequence([Call   as call1, Call(s, 0) as call2]) =>
            when (s.IsGenerated)
            {
              flat.Add(call1);
              flat.Add(call2);
              return
            }
          | _ => ()
        }
        flat.Add(rule);
      }
      tryExtractSpaceSequence(LeftRule.Typing(_baseRule, bp1, None(), context, options));
      foreach (rule in RightRules)
        tryExtractSpaceSequence(rule.Typing(_baseRule, bp2, None(), context, options));
      def rules =  flat.NToList();
      def type  = MakeType(rules.Map(_.Type));
      Rule.Sequence(this.Location, type, MakeName(_fieldName, rules, context), rules);

    | Not =>
        def rule = this.Rule.Typing(None(), 0, None(), context, options);
        Rule.Not(this.Location, RuleType.Void(), "", rule);

    | And => Rule.And(this.Location, RuleType.Void(), "", this.Rule.Typing(None(), 0, None(), context, options))

    | Optional =>
      def rule  = this.Rule.Typing(None(), 0, None(), context, options);
      def type  = if (rule.Type is RuleType.Void) RuleType.Void() else RuleType.Option(rule.Type);
      Rule.Repeat(this.Location, type, _fieldName ?? (rule.FieldName + "Opt"), 0, Some(1), rule);

    | ZeroOrMany =>
      def rule  = this.Rule.Typing(None(), 0, None(), context, options);
      def type  = if (rule.Type is RuleType.Void) RuleType.Void() else RuleType.List(rule.Type);
      Rule.Repeat(this.Location, type, MakePlural(_fieldName, rule, context), 0, None(), rule);

    | OneOrMany =>
      def rule  = this.Rule.Typing(None(), 0, None(), context, options);
      def type  = if (rule.Type is RuleType.Void) RuleType.Void() else RuleType.List(rule.Type);
      Rule.Repeat(this.Location, type, MakePlural(_fieldName, rule, context), 1, None(), rule);

    | FieldName1 => this.Rule.Typing(_baseRule, _precedence, Some(Name.Value()), context, options)
    | FieldName2 => this.Rule.Typing(_baseRule, _precedence, Some(Name.Value()), context, options)
    | Char       => StringRuleTyping(CharLiteral.Location, CharLiteral.Value().ToString(), _fieldName, context, options)
    | String     => StringRuleTyping(StringLiteral.Location, StringLiteral.Value().ToString(), _fieldName, context, options)
    | Rounds     => this.Rule.Typing(_baseRule, _precedence, _fieldName, context, options)
    | Call       => CallRuleTyping(_baseRule, _precedence, _fieldName, context, options, QualifiedName, BindingPower)
    | ZeroOrManyWithSeparator =>
      def rule    = this.Rule.Typing(None(), 0, None(), context, options);
      def sepRule = SeparatorRule.Typing(None(), 0, None(), context, options);
      def type    = MakeType(rule, sepRule);
      Rule.RepeatWithSeparator(this.Location, type, MakePlural(_fieldName, rule, sepRule, context), 0, None(), rule, sepRule, false);

    | ZeroOrManyWithHangingSeparator =>
      def rule    = this.Rule.Typing(None(), 0, None(), context, options);
      def sepRule = SeparatorRule.Typing(None(), 0, None(), context, options);
      def type    = MakeType(rule, sepRule);
      Rule.RepeatWithSeparator(this.Location, type, MakePlural(_fieldName, rule, sepRule, context), 0, None(), rule, sepRule, true);

    | OneOrManyWithSeparator =>
        def rule    = this.Rule.Typing(None(), 0, None(), context, options);
        def sepRule = SeparatorRule.Typing(_baseRule, 0, None(), context, options);
        def type    = MakeType(rule, sepRule);
        Rule.RepeatWithSeparator(this.Location, type, MakePlural(_fieldName, rule, sepRule, context), 1, None(), rule, sepRule, false);

    | OneOrManyWithHangingSeparator =>
      def rule    = this.Rule.Typing(None(), 0, None(), context, options);
      def sepRule = SeparatorRule.Typing(_baseRule, 0, None(), context, options);
      def type    = MakeType(rule, sepRule);
      Rule.RepeatWithSeparator(this.Location, type, MakePlural(_fieldName, rule, sepRule, context), 1, None(), rule, sepRule, true);
  }

  Rule.InferName() : string
  {
    | Sequence => LeftRule.InferName()
    | Optional => Rule.InferName() + "Opt"
    | FieldName1
    | FieldName2 => Name.GetText()
    | Char   => CharLiteral.Value().ToString()
    | String => StringLiteral.Value().ToString()
    | Rounds => Rule.InferName()
    | Call   => QualifiedName.Parts().LastOrDefault("")
    | ZeroOrMany
    | OneOrMany
    | ZeroOrManyWithSeparator
    | ZeroOrManyWithHangingSeparator
    | OneOrManyWithSeparator
    | OneOrManyWithHangingSeparator => MakePlural(Rule.InferName())
    | _ => ""
  }
} // calcs Compile for N2Syntax

Using of named external calculations:

Code Block
def parseResult = parserHost.DoParsing(source, N2Syntax.GrammarImpl.StartRuleDescriptor);
when (parseResult.IsSuccess)
{
  def start = Compile.N2Syntax.Start(parseResult); // Get entry poin to 'Compile' calculations.
  start.Typing(); // call calculation
}

If we will create additional syntax module which extend rules from N2Syntax we must implement Compile calculations for it. This implementation must contains overloading for each calculation of each extendable rule which be extended in the additional syntax module.