<commit_before>from string import Template

from outsourcer import CodeBuilder, Code, Val

from . import expressions as ex
from .expressions import (
    TEXT, POS, Choice, Class, Ref, Right, Rule, Skip, visit
)


def generate_source_code(docstring, nodes):
    out = CodeBuilder()
    out.add_docstring(docstring)
    out += Code(_program_setup)

    # Collect all the rules and stuff.
    rules, ignored = [], []
    start_rule = None

    for node in nodes:
        # Just add Python sections directly to the program.
        if isinstance(node, (ex.PythonExpression, ex.PythonSection)):
            out += Code(node.source_code)
            continue

        rules.append(node)

        if node.is_ignored:
            ignored.append(node)

        if start_rule is None and node.name and node.name.lower() == 'start':
            start_rule = node

    if start_rule is not None and start_rule.is_ignored:
        raise Exception(
            f'The {start_rule!r} rule may not have the "ignored" modifier.'
        )

    if not rules:
        raise Exception('Expected one or more grammar rules.')

    visited_names = set()
    for rule in rules:
        if rule.name is not None and rule.name.startswith('_'):
            raise Exception(
                'Grammar rule names must start with a letter. Found a rule that'
                f' starts with an underscore: "{rule.name}". '<commit_msg>Update error message.<commit_after>from string import Template

from outsourcer import CodeBuilder, Code, Val

from . import expressions as ex
from .expressions import (
    TEXT, POS, Choice, Class, Ref, Right, Rule, Skip, visit
)


def generate_source_code(docstring, nodes):
    out = CodeBuilder()
    out.add_docstring(docstring)
    out += Code(_program_setup)

    # Collect all the rules and stuff.
    rules, ignored = [], []
    start_rule = None

    for node in nodes:
        # Just add Python sections directly to the program.
        if isinstance(node, (ex.PythonExpression, ex.PythonSection)):
            out += Code(node.source_code)
            continue

        rules.append(node)

        if node.is_ignored:
            ignored.append(node)

        if start_rule is None and node.name and node.name.lower() == 'start':
            start_rule = node

    if start_rule is not None and start_rule.is_ignored:
        raise Exception(
            f'The {start_rule!r} rule must not have the "ignore" modifier.'
        )

    if not rules:
        raise Exception('Expected one or more grammar rules.')

    visited_names = set()
    for rule in rules:
        if rule.name is not None and rule.name.startswith('_'):
            raise Exception(
                'Grammar rule names must start with a letter. Found a rule that'
                f' starts with an underscore: "{rule.name}". '
{'fraction_non_alphanumeric': 0.08570412517780938, 'fraction_numerical': 0.0, 'mean_word_length': 2.3729016786570742, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1641095', 'n_tokens_mistral': 797, 'n_tokens_neox': 768, 'n_words': 282}