LCOV - code coverage report
Current view: top level - src - grammar_printer.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 73.5 % 49 36
Test Date: 2026-08-24 04:55:06 Functions: - 0 0
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright 2026 The Authors. See the AUTHORS file for details.
       2              : //
       3              : // Licensed under the Apache License, Version 2.0 (the "License");
       4              : // you may not use this file except in compliance with the License.
       5              : // You may obtain a copy of the License at
       6              : //
       7              : //      https://www.apache.org/licenses/LICENSE-2.0
       8              : //
       9              : // Unless required by applicable law or agreed to in writing, software
      10              : // distributed under the License is distributed on an "AS IS" BASIS,
      11              : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12              : // See the License for the specific language governing permissions and
      13              : // limitations under the License.
      14              : 
      15              : import 'grammar.dart';
      16              : 
      17              : class GrammarPrinter extends ElementVisitor<Map<String, String>> {
      18              :   final _rules = <Rule>{};
      19              :   final Grammar grammar;
      20              :   final String Function(Map<String, String>) printerFunction;
      21              : 
      22            1 :   GrammarPrinter(this.grammar, {this.printerFunction = formatOutputText});
      23              : 
      24            1 :   @override
      25            4 :   String toString() => printerFunction(visitElement(grammar));
      26              : 
      27              :   /// Prints the results from GrammarPrinter in a readable format.
      28              :   ///
      29              :   /// The space between the rule names and their definition is set to
      30              :   /// a standard width based on the longest rule name.
      31            1 :   static String formatOutputText(Map<String, String> rules) {
      32            1 :     final maxWidth = rules.keys
      33            1 :         .reduce((a, b) => a.length > b.length ? a : b)
      34            1 :         .length;
      35              : 
      36            1 :     return rules.entries
      37            6 :         .map((entry) => '${entry.key.padRight(maxWidth)} := ${entry.value}')
      38            1 :         .toList()
      39            1 :         .join('\n');
      40              :   }
      41              : 
      42            0 :   Map<String, String> formatOutputMap() => visitElement(grammar);
      43              : 
      44            1 :   Map<String, String> _extractRules(ElementSequence elements) {
      45            1 :     final r = <String, String>{}; // Start empty
      46              : 
      47            2 :     for (final element in elements) {
      48            1 :       if (element is Rule) {
      49            0 :         r.addAll(visitRule(element));
      50              :       } else {
      51              :         // Visit the nested element AND merge its results into our map
      52            2 :         r.addAll(visitElement(element));
      53              :       }
      54              :     }
      55              :     return r;
      56              :   }
      57              : 
      58            0 :   @override
      59              :   Map<String, String> visitAlternativeLiterals(AlternativeLiterals element) =>
      60            0 :       {};
      61              : 
      62            1 :   @override
      63              :   Map<String, String> visitAlternatives(Alternatives alternatives) =>
      64            2 :       _extractRules(alternatives.elements);
      65              : 
      66            0 :   @override
      67              :   Map<String, String> visitConcatenation(Concatenation concatenation) =>
      68            0 :       _extractRules(concatenation.sequence);
      69              : 
      70            1 :   @override
      71              :   Map<String, String> visitGrammar(Grammar grammar) =>
      72            2 :       visitElement(grammar.entryRule);
      73              : 
      74            1 :   @override
      75            2 :   Map<String, String> visitGroup(Group group) => _extractRules(group.elements);
      76              : 
      77            1 :   @override
      78            1 :   Map<String, String> visitLiteralElement(LiteralElement element) => {};
      79              : 
      80            1 :   @override
      81              :   Map<String, String> visitOptionalSequence(OptionalSequence sequence) =>
      82            2 :       _extractRules(sequence.elements);
      83              : 
      84            1 :   @override
      85              :   Map<String, String> visitRepetition(Repetition repetition) =>
      86            3 :       _extractRules([repetition.element]);
      87              : 
      88            1 :   @override
      89              :   Map<String, String> visitRule(Rule rule) {
      90            2 :     if (_rules.contains(rule)) {
      91            0 :       return {};
      92              :     }
      93            2 :     _rules.add(rule);
      94            7 :     return {rule.name: rule.element.toString(), ...visitElement(rule.element)};
      95              :   }
      96              : 
      97            0 :   @override
      98              :   Map<String, String> visitSequence(Sequence sequence) =>
      99            0 :       _extractRules(sequence.elements);
     100              : 
     101            1 :   @override
     102            1 :   Map<String, String> visitValueRange(ValueRange range) => {};
     103              : 
     104            1 :   @override
     105            1 :   Map<String, String> visitCharacterElement(CharacterElement element) => {};
     106              : 
     107            0 :   @override
     108            0 :   Map<String, String> visitEmptyElement(EmptyElement element) => {};
     109              : 
     110            0 :   @override
     111            0 :   Map<String, String> visitNegativeLookahead(NegativeLookahead element) => {};
     112              : }
        

Generated by: LCOV version 2.0-1